Подтвердить что ты не робот

JavaScript: indexOf против Match при поиске строк?

В отличие от читаемости, существуют ли какие-либо заметные различия (возможно, производительность) между использованием

str.indexOf("src") 

и

str.match(/src/)

Я лично предпочитаю match (и regexp), но коллеги, похоже, идут в другую сторону. Нам было интересно, важно ли это...?

EDIT:

Вначале я должен был сказать, что это для функций, которые будут выполнять частичное согласование простой строки (для получения идентификаторов в атрибутах класса для JQuery), а не для полного поиска регулярных выражений с помощью подстановочных знаков и т.д.

class='redBorder DisablesGuiClass-2345-2d73-83hf-8293' 

Таким образом, его различие между:

string.indexOf('DisablesGuiClass-');

VS

string.match(/DisablesGuiClass-/)
4b9b3361

Ответ 1

RegExp действительно медленнее, чем indexOf (вы можете увидеть его здесь), хотя обычно это не должно быть проблемой. С RegExp вы также должны убедиться, что строка правильно экранирована, что является дополнительной вещью, о которой нужно подумать.

Обе эти проблемы в стороне, если два инструмента делают именно то, что вам нужно, почему бы не выбрать более простой?

Ответ 2

Ваше сравнение может быть не совсем справедливым. indexOf используется с обычными строками и поэтому очень быстро; match принимает регулярное выражение - конечно, это может быть медленнее по сравнению, но если вы хотите выполнить регулярное выражение, вы не уйдете далеко с indexOf. С другой стороны, механизмы регулярного выражения могут быть оптимизированы и в последние годы улучшаются в производительности.

В вашем случае, когда вы ищете стенографическую строку, indexOf должно быть достаточно. Тем не менее, существует еще одно приложение для регулярных выражений: если вам нужно сопоставить целые слова и хотите избежать совпадений подстрок, тогда регулярные выражения дают вам "якорные граничные привязки". Например:

indexOf('bar')

найдет bar три раза в bar, fubar, barmy, тогда как

match(/\bbar\b/)

будет соответствовать только bar, если он не является частью более длинного слова.

Как вы можете видеть в комментариях, были сделаны некоторые сравнения, которые показывают, что регулярное выражение может быть быстрее, чем indexOf - если оно критично для производительности, вам может понадобиться профиль вашего кода.

Ответ 3

Если вы пытаетесь найти вхождения подстроки без учета регистра, то match кажется более быстрым, чем комбинация indexOf и toLowerCase()

Отметьте здесь - http://jsperf.com/regexp-vs-indexof/152

Ответ 4

Вы спрашиваете, предпочтительнее ли str.indexOf('target') или str.match(/target/). Как предполагали другие плакаты, варианты использования и типы возврата этих методов различны. Первый спрашивает: "Где в str я могу сначала найти 'target'?" Второй спрашивает: "str соответствует регулярному выражению, и если да, то каковы все совпадения для любых связанных групп захвата?"

Проблема заключается в том, что ни один из них не разработан специально для того, чтобы задать более простой вопрос: "содержит ли строка подстроку?" Есть что-то, что явно предназначено для этого:

var doesStringContainTarget = /target/.test(str);

Существует несколько преимуществ использования regex.test(string):

  • Он возвращает логическое значение, которое вас беспокоит
  • Это более результативно, чем str.match(/target/) (и соперники str.indexOf('target'))
  • Если по какой-то причине str есть undefined или null, вы получите false (желаемый результат) вместо того, чтобы бросать TypeError

Ответ 5

Использование indexOf должно, теоретически, быть быстрее, чем регулярное выражение, когда вы просто ищете какой-либо простой текст, но вы должны сделать некоторые сравнительные тесты самостоятельно, если вас беспокоит производительность.

Если вы предпочитаете match, и он достаточно быстро для ваших нужд, идите за ним.

Для чего я согласен с вашими коллегами по этому вопросу: я бы использовал indexOf при поиске простой строки и использовал match и т.д. только тогда, когда мне нужна дополнительная функциональность, предоставляемая регулярными выражениями.

Ответ 6

Показатель производительности indexOf будет, по крайней мере, немного быстрее, чем match. Все сводится к конкретной реализации. При принятии решения о том, что использовать, задайте себе следующий вопрос:

Будет ли целочисленный индекс достаточным или я нужна функциональность RegExp результат совпадения?

Ответ 7

Возвращаемые значения различаются

Помимо последствий для производительности, которые рассматриваются другими ответами, важно отметить, что возвращаемые значения для каждого метода различны; поэтому методы не могут быть просто заменены без изменения вашей логики.

Возвращаемое значение .indexOf: integer

Индекс внутри вызывающего объекта String первого вхождения указанного значения, начиная поиск в fromIndex.
Возвращает -1, если значение не найдено.

Возвращаемое значение .match: array

Массив, содержащий весь результат совпадения и любые скопированные совпадающие результаты.
Возвращает null, если совпадений не было.

Потому что .indexOf возвращает 0, если вызывающая строка начинается с указанного значения, простейший правдивый тест не удастся.

Например:

Учитывая этот класс...

class='DisablesGuiClass-2345-2d73-83hf-8293 redBorder' 

... значения возврата для каждого будут отличаться:

//  returns `0`, evaluates to `false`
if (string.indexOf('DisablesGuiClass-')) {
    … // this block is skipped.
}

против.

//  returns `["DisablesGuiClass-"]`, evaluates to `true`
if (string.match(/DisablesGuiClass-/)) { 
    … // this block is run.
}

Правильный способ запуска правдивого теста с возвратом из .indexOf заключается в проверке на -1:

if (string.indexOf('DisablesGuiClass-') !== -1) {
//  ^returns `0`                        ^evaluates to `true`
    … // this block is run.
}

Ответ 8

всегда используйте indexOf для существования подстрок и match только тогда, когда вам это действительно нужно. т.е. если вы искали слово src в строке, которая также может содержать altsrc, тогда aString.match(/\bsrc\b/) действительно более подходит.

Ответ 10

Здесь все возможные способы (относительно) поиска строки

//1. включает (введено в ES6)

var string = "string to search for substring",
    substring = "sea";
string.includes(substring);

//2. string.indexOf

var string = "string to search for substring",
    substring = "sea";
string.indexOf(substring) !== -1;

//3. RegExp: test

var string = "string to search for substring",
    expr = /sea/;  // no quotes here
expr.test(string);

//4. string.match

var string = "string to search for substring",
    expr = "/sea/";
string.match(expr);

//5. string.search

var string = "string to search for substring",
    expr = "/sea/";
string.search(expr);

Вот источник: https://koukia.ca/top-6-ways-to-search-for-a-string-in-javascript-and-performance-benchmarks-ce3e9b81ad31

Бенчмарки вроде бы крутили специально для es6 включает, читайте комментарии.

В резюме:

если вам не нужны спички. => Либо вам нужно регулярное выражение и поэтому используйте тест. В противном случае es6 включает или indexOf. Все еще тест против indexOf близки.

И для включает vs indexOf:

Кажется, они одинаковы: https://jsperf.com/array-indexof-vs-includes/4 (если бы это было иначе, это было бы странно, они в основном выполняют то же самое, за исключением различий, которые они выставляют, проверьте это)

И для моего собственного теста. здесь это http://jsben.ch/fFnA0. Вы можете протестировать его (это зависит от браузера) [тестировать несколько раз] здесь, как это выполнялось (многократный запуск indexOf и включает в себя один удар другого, и они близки). Так они одинаковы. [здесь используется та же тестовая платформа, что и в статье выше].

enter image description here enter image description here

А вот длинная текстовая версия (в 8 раз длиннее) http://jsben.ch/wSBA2

enter image description here

Протестировал и chrome, и firefox, тоже самое.

Обратите внимание, что jsben.ch не обрабатывает переполнение памяти (или ограничивает правильно. Оно не отображает никаких сообщений), поэтому результат может быть неправильным, если вы добавите более 8 дубликатов текста (8 работают хорошо). Но вывод для очень большого текста - все три работают одинаково. Иначе для коротких indexOf и include одинаковы и тестировать немного медленнее. или может быть таким же, как казалось в chrome (firefox 60 медленнее).

Обратите внимание на jsben.ch: не волнуйтесь, если вы получите непоследовательный результат. Попробуйте другое время и посмотрите, соответствует ли оно или нет. Измените браузер, иногда они просто работают неправильно. Ошибка или плохая обработка памяти. Или что-то.

например:

enter image description here

Здесь также мой тест на jsperf (подробности и обработка графиков для нескольких браузеров)

(верх хромированный)

обычный текст https://jsperf.com/indexof-vs-includes-vs-test-2019
резюме: включает и indexOf имеют одинаковую производительность. тест медленнее.

enter image description here enter image description here (кажется, все три выполняют одинаково в chrom)

Длинный текст (в 12 раз длиннее обычного) https://jsperf.com/indexof-vs-include-vs-test-2019-long-text-str/
резюме: все три выполняют одинаково. (хром и Firefox) enter image description here

очень короткая строка https://jsperf.com/indexof-vs-includes-vs-test-2019-too-short-string/
резюме: включает и indexOf выполняют то же самое и тестируют медленнее.

enter image description here

Примечание: о бенчмарке выше. Для очень короткой строковой версии (jsperf) была большая ошибка для chrome. Видя моими глазами. около 60 выборок было выполнено для обоих indexOf и включает в себя один и тот же способ (повторяется много раз). И тест немного меньше и так медленнее. не обманывайтесь неправильным графиком. Это ясно неправильно. Тот же тест работает нормально для Firefox, конечно, это ошибка.

Вот иллюстрация: (первое изображение было тестом на Firefox) enter image description here waaaa. Внезапно indexOf стал суперменом. Но, как я уже сказал, я провел тест и посмотрел на количество выборок, которое было около 60. И indexOf, и include, и они выполнили то же самое. Ошибка на jspref. За исключением этого (возможно, из-за проблемы, связанной с ограничением памяти) все остальное было согласованным, оно дает больше подробностей. И вы видите, как много всего происходит в реальном времени.

Окончательное резюме

indexOf против включает => Та же производительность

test => может быть медленнее для коротких строк или текста. И то же самое для длинных текстов. И это имеет смысл для накладных расходов, которые добавляет двигатель регулярных выражений. В хроме это казалось совершенно неважным.