Я пытаюсь найти позиции всех вхождений строки в другой строке без учета регистра.
Например, учитывая строку:
Я научился играть на укулеле в Ливане.
и строку поиска le
, я хочу получить массив:
[2, 25, 27, 33]
Обе строки будут переменными, т.е. я не могу жестко запрограммировать их значения.
Я подумал, что это простая задача для регулярных выражений, но после долгих попыток найти то, которое подойдет, мне не повезло.
Я нашел этот пример того, как сделать это, используя .indexOf()
, но, конечно, должен быть более краткий способ сделать это?
источник
le
быть переменная строка? Даже при использованииnew Regexp(str);
специальных символов таится опасность, например поиск$2.50
.regex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));
ИМХО было бы что-то вроде бы поближе. Я не уверен, есть ли в js встроенный механизм экранирования регулярных выражений.new RegExp(searchStr)
будет так, и да, в общем случае вам придется избегать специальных символов. На самом деле этого не стоит делать, если вам не нужен такой уровень общности.searchStr=aaa
и чтоstr=aaaaaa
. Тогда вместо того, чтобы найти 4 случая, ваш код найдет только 2, потому что вы делаете пропускиsearchStr.length
в цикле.Вот бесплатная версия регулярных выражений:
РЕДАКТИРОВАТЬ : и если вы хотите сопоставить такие строки, как 'aaaa' и 'aa', чтобы найти [0, 2], используйте эту версию:
источник
var result = indexes('aaaa', 'aa')
? Ожидаемый результат должен быть[0, 1, 2]
или[0, 2]
?i+=find.length;
i++
Вы точно можете это сделать!
Изменить: научиться писать RegExp
Кроме того, я понял, что это не совсем то , что вы хотите, поскольку это
lastIndex
говорит нам о конце иглы, а не о начале, но это близко - вы можете вставитьre.lastIndex-needle.length
в массив результатов ...Изменить: добавление ссылки
Ответ @Tim Down использует объект результатов из RegExp.exec (), и все мои ресурсы Javascript затушевывают его использование (кроме предоставления вам совпадающей строки). Так что когда он использует
result.index
, это какой-то безымянный Match Object. В MDC-описании exec этот объект на самом деле описан достаточно подробно.источник
Один лайнер с использованием
String.protype.matchAll
(ES2020):Используя ваши ценности:
Если вы беспокоитесь о том, чтобы сделать разворот и
map()
в одну строку, я запустил его сfor...of
циклом для миллиона итераций (используя ваши строки). Один лайнер в среднем составляет 1420 мс, аfor...of
на моей машине - 1150 мс. Это немаловажная разница, но один лайнер будет работать нормально, если вы проведете только несколько совпадений.Смотрите
matchAll
на канюсеисточник
Если вы просто хотите найти положение всех совпадений, я хотел бы указать вам на небольшой прием:
Это может быть неприменимо, если у вас есть RegExp с переменной длиной, но для некоторых это может быть полезно.
Это чувствительно к регистру. Для нечувствительности к регистру используйте
String.toLowerCase
функцию before.источник
Вот простой фрагмент кода:
источник
Следуйте ответ @jcubic, его решение вызвало небольшие путает для моего случая
К примеру
var result = indexes('aaaa', 'aa')
он будет возвращать[0, 1, 2]
вместо[0, 2]
Так что я обновил прикусило решение , как показано ниже , чтобы соответствовать моему случаю
источник
Спасибо за все отклики. Я просмотрел их все и придумал функцию, которая дает первому и последнему индекс каждого вхождения подстроки «игла». Я выкладываю это здесь на случай, если это кому-то поможет.
Обратите внимание, что это не то же самое, что исходный запрос, только начало каждого вхождения. Это больше подходит для моего случая использования, потому что вам не нужно сохранять длину иглы.
источник
Проверьте это решение, которое также сможет найти такую же строку символов, дайте мне знать, если что-то отсутствует или не так.
источник
Вот мое бесплатное решение с регулярными выражениями.
источник
Я бы порекомендовал ответ Тима. Однако @blazs утверждает: «Предположим, что searchStr = aaa и что str = aaaaaa. Тогда вместо поиска 4 вхождений ваш код найдет только 2, потому что вы делаете пропуски по searchStr.length в цикле», что верно, если посмотреть на Код Тима, а именно эта строка здесь: startIndex = index + searchStrLen; Код Тима не сможет найти экземпляр строки, в которой выполняется поиск, которая находится в пределах самой длины. Итак, я изменил ответ Тима:
Изменение его на «+ 1» вместо «+ searchStrLen» позволит индексу 1 быть в массиве индексов, если у меня есть str «aaaa» и searchStr «aa».
Второй ответ
У меня есть еще один фрагмент кода, который тоже работает. Он имитирует ответ, предоставленный @YuJie, за исключением того, что этот более компактный, чем ответ Ю Джи:
Однако недостатком этого фрагмента является то, что он может занять немного больше времени, чем первый, поскольку первый использует встроенную функцию JavaScript indexOf (), тогда как второй немного похож на старую поговорку "re -изобретая колесо ". Итак, в целом, я бы порекомендовал свой первый ответ вместо этого. PS Если кому-то нужны комментарии в коде, объясняющие, как он работает, скажите об этом, и я буду рад ответить на запрос.
источник
источник
приведенный ниже код сделает эту работу за вас:
источник
Используйте String.prototype.match .
Вот пример из самой документации MDN:
источник