대소 문자를 구분하지 않는 다른 문자열에서 문자열의 모든 발생 위치를 찾으려고합니다.
예를 들어 다음과 같은 문자열이 있습니다.
레바논에서 우쿨렐레를 배웠습니다.
및 검색 문자열 le
, 배열을 얻고 싶습니다.
[2, 25, 27, 33]
두 문자열 모두 변수가됩니다. 즉, 값을 하드 코딩 할 수 없습니다.
정규 표현식으로는 쉬운 일이라고 생각했지만, 작동하는 것을 찾기 위해 한동안 고생 한 끝에 운이 없었습니다.
를 사용하여이 작업을 수행하는 방법에 대한 이 예제 를 찾았 .indexOf()
지만 확실히 더 간결한 방법이 있어야합니까?
답변
var str = "I learned to play the Ukulele in Lebanon."
var regex = /le/gi, result, indices = [];
while ( (result = regex.exec(str)) ) {
indices.push(result.index);
}
최신 정보
검색 문자열이 변수 여야한다는 원래 질문에서 발견하지 못했습니다. 를 사용하는이 사건을 처리하기 위해 다른 버전을 작성 indexOf
했으므로 시작했던 곳으로 돌아 왔습니다. 주석에서 Wrikken이 지적했듯이 정규식을 사용하는 일반적인 경우에 이것을 수행하려면 특수 정규식 문자를 이스케이프해야합니다.이 시점에서 정규식 솔루션이 가치가있는 것보다 더 골칫거리가된다고 생각합니다.
function getIndicesOf(searchStr, str, caseSensitive) {
var searchStrLen = searchStr.length;
if (searchStrLen == 0) {
return [];
}
var startIndex = 0, index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>
답변
다음은 정규식 무료 버전입니다.
function indexes(source, find) {
if (!source) {
return [];
}
// if find is empty string return all indexes.
if (!find) {
// or shorter arrow function:
// return source.split('').map((_,i) => i);
return source.split('').map(function(_, i) { return i; });
}
var result = [];
for (i = 0; i < source.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
return result;
}
indexes("I learned to play the Ukulele in Lebanon.", "le")
편집 : ‘aaaa’및 ‘aa’와 같은 문자열을 일치시켜 [0, 2]를 찾으려면이 버전을 사용하십시오.
function indexes(source, find) {
if (!source) {
return [];
}
if (!find) {
return source.split('').map(function(_, i) { return i; });
}
var result = [];
var i = 0;
while(i < source.length) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
i += find.length;
} else {
i++;
}
}
return result;
}
답변
당신은 확실히 할 수 있습니다!
//make a regular expression out of your needle
var needle = 'le'
var re = new RegExp(needle,'gi');
var haystack = 'I learned to play the Ukulele';
var results = new Array();//this is the results you want
while (re.exec(haystack)){
results.push(re.lastIndex);
}
편집 : RegExp 철자 배우기
또한 바늘의 끝이 시작이 아니라 끝이 아니라는 것을 알려주기 때문에 이것이 정확히 원하는 것이 아니라는 것을 깨달았 lastIndex
습니다. 가깝습니다 re.lastIndex-needle.length
. 결과 배열로 밀어 넣을 수 있습니다 .
편집 : 링크 추가
@Tim Down의 대답은 RegExp.exec ()의 결과 객체를 사용하고 모든 Javascript 리소스는 사용에 대해 광택이 있습니다 (일치하는 문자열을 제공하는 것 제외). 그래서 그가를 사용할 때 result.index
그것은 일종의 이름없는 Match Object입니다. exec 의 MDC 설명에서 실제로이 개체를 상당히 자세하게 설명합니다.
답변
String.protype.matchAll
(ES2020)을 사용하는 라이너 1 개 :
[...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index)
가치 사용 :
const sourceStr = 'I learned to play the Ukulele in Lebanon.';
const searchStr = 'le';
const indexes = [...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index);
console.log(indexes); // [2, 25, 27, 33]
스프레드와 map()
한 줄을 하는 것이 걱정된다면 , 나는 for...of
(당신의 문자열을 사용하여) 백만 번의 반복을위한 루프로 그것을 실행했습니다 . 하나의 라이너는 평균 1420ms이고 for...of
내 컴퓨터 의 평균은 1150ms입니다. 그것은 사소한 차이는 아니지만 몇 번의 성냥 만한다면 한 라이너가 잘 작동합니다.
답변
모든 경기의 위치를 찾고 싶다면 약간의 해킹을 알려 드리고자합니다.
var haystack = 'I learned to play the Ukulele in Lebanon.',
needle = 'le',
splitOnFound = haystack.split(needle).map(function (culm)
{
return this.pos += culm.length + needle.length
}, {pos: -needle.length}).slice(0, -1); // {pos: ...} – Object wich is used as this
console.log(splitOnFound);
가변 길이의 RegExp가있는 경우에는 적합하지 않을 수 있지만 일부는 유용 할 수 있습니다.
대소 문자를 구분합니다. 케이스 무감각의 경우 String.toLowerCase
이전 기능을 사용하십시오 .
답변
다음은 간단한 코드입니다.
function getIndexOfSubStr(str, searchToken, preIndex, output){
var result = str.match(searchToken);
if(result){
output.push(result.index +preIndex);
str=str.substring(result.index+searchToken.length);
getIndexOfSubStr(str, searchToken, preIndex, output)
}
return output;
};
var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var searchToken ="my";
var preIndex = 0;
console.log(getIndexOfSubStr(str, searchToken, preIndex, []));
답변
@jcubic의 대답을 따르십시오. 그의 솔루션은 내 경우에 약간의 혼란을 일으켰습니다.
예를 들어 대신 var result = indexes('aaaa', 'aa')
반환
되므로 내 경우와 일치하도록 그의 솔루션을 아래와 같이 약간 업데이트했습니다.[0, 1, 2]
[0, 2]
function indexes(text, subText, caseSensitive) {
var _source = text;
var _find = subText;
if (caseSensitive != true) {
_source = _source.toLowerCase();
_find = _find.toLowerCase();
}
var result = [];
for (var i = 0; i < _source.length;) {
if (_source.substring(i, i + _find.length) == _find) {
result.push(i);
i += _find.length; // found a subText, skip to next position
} else {
i += 1;
}
}
return result;
}