Найшвидший спосіб перевірити рядок, що містить ще одну підрядку в JavaScript?


163

Я працюю з проблемою продуктивності на JavaScript. Тому я просто хочу запитати: який найшвидший спосіб перевірити, чи містить рядок іншу підрядку (мені просто потрібне булеве значення)? Ви можете запропонувати свою ідею та зразок коду фрагмента?


Ви питаєте про фіксовану підрядку чи вам потрібен регулярний вираз (я трохи заплутаний у використанні regexтегу)?
Тім Піцкер

1
Ця публікація буде корисною .. stackoverflow.com/questions/1789945/javascript-string-contains
mtk

Як щодо розділення рядка на масив навколо пробілу та перетину масиву? stackoverflow.com/questions/1885557 / ...
giorgio79

Відповіді:


315

У вас є дві можливості:

  1. Регулярний вираз :

    (new RegExp('word')).test(str)
    // or
    /word/.test(str)
    
  2. indexOf:

    str.indexOf('word') !== -1

Регулярні вирази здаються швидшими (принаймні в Chrome 10).

Тест на продуктивність - короткий стог сіна.
Тест на ефективність - довгий стог сіна


Оновлення 2011 року:

Не можна з впевненістю сказати, який метод швидший. Відмінності між браузерами величезні. Хоча в Chrome 10, indexOfздається, швидше, у Safari 5 indexOfявно повільніше, ніж будь-який інший метод.

Ви повинні побачити і спробувати себе. Це залежить від ваших потреб. Наприклад, нечутливий до регістру пошук проходить швидше за допомогою регулярних виразів.


Оновлення 2018 року:

Просто, щоб врятувати людей від запуску тестів, ось поточні результати для більшості звичайних веб-переглядачів, відсотки вказують на підвищення продуктивності за наступний найшвидший результат (який залежить від браузерів):

Chrome: indexOf (~ 98% швидше) <-- wow
Firefox: кешований RegExp (~ 18% швидше)
IE11: кешований RegExp (~ 10% швидше)
Край: indexOf (~ 18% швидше)
Safari: кешований RegExp (~ 0,4% швидше)

Зауважте, що кешований RegExp є: var r = new RegExp('simple'); var c = r.test(str);на відміну від:/simple/.test(str)


3
Це може бути трохи швидше, лише якщо текст для пошуку відомий до початку (тобто не зберігається в змінній), тому що регулярний вираз створюється двигуном JavaScript під час розбору. Якщо ви хочете шукати рядок, що міститься в змінній всередині іншої рядкової змінної, indexOf є найшвидшим, тому що вам потрібно буде створити об’єкт RegExp і обробити рядок, щоб уникнути спеціальних символів тощо.
Stephen Chung

з досвіду, indexOf може бути швидшим для нечутливого пошуку, якщо ви використовуєте .toLowerCase у будь-якому, що ви шукаєте спочатку
Hayk Saakian

Я пишу додаток Office 2013, використовуючи API Office Office Microsoft Microsoft, а використання indexOfне працює. Я не впевнений, чому. Використання Regex хоча. Це кращий випадок, але інші можуть зіткнутися з тією ж проблемою.
Енді Мерсер

Будь-яка причина substr () не є одним із можливих рішень? Я думаю, це набагато швидше, ніж рішення RegEx у багатьох ситуаціях. Я не знаю, як це порівнювати з indexOf (), хоча (тому, якщо ви вийшли з нього, тому що він завжди гірший, ніж indexOf (), це добре, можливо, додайте до цього записку.) EDIT: ця посилання JSperf показує цікаве результати. Коротка версія: indexOf () - найшвидший з усіх методів, але це може змінюватися залежно від довжини рядка та будь-яких повторюваних шаблонів.
Byson

1
@Bison: substr можна використовувати лише тоді, коли ви вже знаєте, де шукати. Я зосередився лише на загальних рішеннях.
Фелікс Клінг

17

Це працює для вас?

string1.indexOf(string2) >= 0

Правка: Це може бути не швидше, ніж RegExp, якщо рядок2 містить повторювані шаблони. У деяких браузерах indexOf може бути набагато повільніше, ніж RegExp. Дивіться коментарі.

Редагувати 2: RegExp може бути швидшим, ніж indexOf, коли рядки дуже довгі та / або містять повторювані шаблони. Дивіться коментарі та відповідь @ Фелікса.


але як це порівняти з іншими методами? Це найшвидший чи це лише один із багатьох методів цього?
Chii

Це має бути швидким, оскільки він реалізований самим JavaScript (тобто він працює з власним кодом). Будь-який інший метод, заснований на коді JavaScript, буде повільнішим. Якщо ви знаєте точний рядок, регулярний вираз може бути трохи швидшим (оскільки двигун JavaScript не повинен ходити по прототипу, щоб знайти .indexOf).
Стівен Чунг

Якщо вам потрібен нечутливий до регістру пошук, вам неодмінно потрібно створити об’єкт RegExp та зателефонувати test.
Стівен Чунг

3
Щойно пройшов тест у Сафарі. indexOf- на величину повільніше, ніж будь-який інший метод. Тож насправді не можна сказати, який метод швидший. Він залежить від браузера до браузера.
Фелікс Клінг

@Felix, це гарне спостереження (ніколи нічого не довіряй, поки ти фактично не спробуєш сам)! Я розпливаюче запам'ятовуючи щось, що говорить у рядках з великою кількістю повторюваних шаблонів, регулярні вирівнювання повинні виконувати швидше, ніж просте впровадження порівняння циклу, оскільки регекс збирається в державні машини, і він може відслідковуватись набагато швидше, ніж прості петлі - що завжди має відповідати- трек до наступного символу. +1 за те, що ви зробили експеримент і вивели це!
Стівен Чунг

17

Найшвидший

  1. (ES6) включає
    var string = "привіт",
    substring = "lo";
    string.includes (підрядка);
  1. ES5 та старіший indexOf
    var string = "привіт",
    substring = "lo";
    string.indexOf (підрядка)! == -1;

http://jsben.ch/9cwLJ

введіть тут опис зображення


8

У ES6 includes()метод використовується для визначення того, чи може одна рядок знаходитися в іншій рядку, повертається trueабо falseяк доречно.

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

Ось jsperf між

var ret = str.includes('one');

І

var ret = (str.indexOf('one') !== -1);

Як результат, показаний у jsperf, схоже, що вони обидва добре.


Чи можу я використовувати "regex" всередині, як включає "аргумент? Як str.includes("x|y"):; пошук літералів "x" або "y" в одному дзвінку.
ptkato

@Patrick, Включити doc, ви не можете використовувати regexйого. Один обхід для вашого питання,str.includes("x") || str.includes('y')
zangw

В результаті покращення JavaScript у Chrome 59 indexOfзначно швидше includes(на 1600% швидше). Незрозуміло, як різниця в 44 мільйони ітерацій на секунду та 777+ мільйонів в / с впливає на продуктивність у реальному світі, проте мобільний, ймовірно, достатньо вигод, який indexOfповинен бути ідеальним вибором.
Чад Леві

7

Я виявив, що за допомогою простого циклу ітерація над усіма елементами рядка та порівняння з використанням charAtвиконує швидше ніж indexOfабо Regex. Код та доказ доступні на JSPerf .

ETA: indexOfі charAtобидва виглядають так само жахливо на Chrome Mobile відповідно до даних Browser Scope, наведених на jsperf.com


Дивно, що ручна функція краще, ніж вбудована, але я думаю, це тому, що голка має лише один символ. Все-таки ...
Мосс

Тестовано в Chrome Mobile 36.0.1985.57 на Apple iPad (iOS 7.1.1). IndexOf швидше. Вибачте
rpax

@rpax CharAt все ще значно швидший на всіх платформах (на основі історії jsperf) за винятком Chrome Mobile, де і IndexOf, і CharAt однаково погано працюють у порівнянні з робочим столом.
wpg4665

1
Я хотів би побачити, як це працює в NodeJS, а також це насправді не гарний приклад, тому що ви шукаєте лише одного символу проти підрядка.
qodeninja

Це взагалі неправдива відповідь. Ви не шукаєте підрядку, лише зустріч одного символу
Генрік Мінтті

3

Для пошуку простого рядка використання методу indexOf () та використання регулярного вираження майже однакове: http://jsperf.com/substring - тож вибирайте, який із них, який видається простіше написати.



1

Це простий спосіб використовувати .match()метод для рядку.

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

Бажаю вам приємного дня, сер!


4
Немає причин, matchколи існує testметод… Перевірте верхню відповідь.
Бергі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.