대소 문자를 구분하지 않는 다른 문자열에서 문자열의 모든 발생 위치를 찾으려고합니다.
예를 들어 다음과 같은 문자열이 있습니다.
레바논에서 우쿨렐레를 배웠습니다.
및 검색 문자열 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;
}
