Как найти индексы всех вхождений одной строки в другую на JavaScript?
Я пытаюсь найти позиции всех вхождений строки в другую строку без учета регистра.
например, учитывая строку:
I learned to play the Ukulele in Lebanon.
и в строке поиска le, Я хочу получить массив:
[2, 25, 27, 33]
обе строки будут переменными, т. е. я не могу жестко кодировать их значения.
Я понял, что это была легкая задача для регулярных выражений, но, спустя некоторое время, чтобы найти тот, который будет работать, у меня не было удача.
нашел как это сделать с помощью .indexOf(), но наверняка должен быть более краткий способ сделать это?
9 ответов:
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) { 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")
вы уверены, что можете это сделать!
//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); }Edit: научитесь писать регулярное выражение
кроме того, я понял, что это не ровно то, что вы хотите, как
lastIndexговорит нам конец иглы не начало, но это близко - вы могли бы нажатьre.lastIndex-needle.lengthв массив результатов...правка: добавление ссылки
в ответе@Tim Down используется объект результатов из регулярного выражения.exec (), и все мои ресурсы Javascript замалчивают его используйте (помимо предоставления вам соответствующей строки). Поэтому, когда он использует
result.index, Это какой-то неназванный объект соответствия. В MDC описание exec, они на самом деле описывают этот объект в приличных деталях.
использовать строку.прототип.матч.
вот пример из самого MDN docs:
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; var regexp = /[A-E]/gi; var matches_array = str.match(regexp); console.log(matches_array); // ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
Если вы просто хотите найти положение всех матчей, я хотел бы указать вам на небольшой хак:
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)это может быть не применимо, если у вас есть регулярное выражение с переменной длиной, но для некоторых это может быть полезно.
следуйте ответу @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; }
вот простой код
function getIndexOfSubStr(str, serchToken, preIndex, output){ var result = str.match(serchToken); if(result){ output.push(result.index +preIndex); str=str.substring(result.index+serchToken.length); getIndexOfSubStr(str, serchToken, preIndex, output) } return output; }; var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' "; var serchToken ="my"; var preIndex = 0; console.log(getIndexOfSubStr(str, serchToken, preIndex, []));
function countInString(searchFor,searchIn){ var results=0; var a=searchIn.indexOf(searchFor) while(a!=-1){ searchIn=searchIn.slice(a*1+searchFor.length); results++; a=searchIn.indexOf(searchFor); } return results; }
приведенный ниже код сделает работу за вас:
function indexes(source, find) { var result = []; for(i=0;i<str.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("hello, how are you", "ar")
Comments