Сравнение строк без учета регистра в JavaScript

Как выполнить сравнение строк без учета регистра в JavaScript?

 Adrien Be25 февр. 2016 г., 11:51
@ Manuell, что означает"a" приходит раньше"A" когда отсортировано. подобно"a" приходит раньше"b", Если это поведение нежелательно, можно захотеть.toLowerCase() каждая буква / строка. то есть."A".toLowerCase().localeCompare( "a".toLowerCase() ) увидетьdeveloper.mozilla.org/en/docs/Web/JavaScript/Reference/...
 Adrien Be25 февр. 2016 г., 16:48
Потому что сравнение, как я полагаю, часто используется для сортировки / упорядочивания строк. Я прокомментировал здесь давным-давно.=== проверим на равенство, но выигралне достаточно хорош для сортировки / упорядочивания строк (см. вопрос, на который я изначально ссылался).
 JLRishe10 янв. 2019 г., 04:25
@manuelllocaleCompare делает сравнение без учета регистра, если вы передаете{ sensitivity: 'accent' } или же{ sensitivity: 'base' } вариант. ,"A".localeCompare("a", undefined, { sensitivity: 'accent' }) === 0
 Adrien Be26 сент. 2014 г., 13:00
смотрите такжеstackoverflow.com/questions/51165/...
 Adrien Be26 сент. 2014 г., 12:43
увидеть недавно добавленные.localeCompare() метод javascript. Поддерживается только современными браузерами на момент написания (IE11 +). увидетьdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
 manuell25 февр. 2016 г., 12:48
@AdrienBe Моя точка зрения: как.localeCompare() относится к "сравнение строк без учета регистра "? Я имею в виду, если вы должны взятьtoLowerCase() маршрут в любом случае, то вы можете просто использовать===  потом ...
 manuell25 февр. 2016 г., 10:22
@AdrienBe"A".localeCompare( "a" ); возвращается1 в консоли Chrome 48.

Ответы на вопрос(12)

РЕДАКТИРОВАТЬ: Этот ответ был первоначально добавлен 9 лет назад. Сегодня вы должны использоватьlocaleCompare сsensitivity: 'accent' опция:

function ciEquals(a, b) {
    return typeof a === 'string' && typeof b === 'string'
        ? a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0
        : a === b;
}

console.log("'a' = 'a'?", ciEquals('a', 'a'));
console.log("'AaA' = 'aAa'?", ciEquals('AaA', 'aAa'));
console.log("'a' = 'á'?", ciEquals('a', 'á'));
console.log("'a' = 'b'?", ciEquals('a', 'b'));

{ sensitivity: 'accent' } говоритlocaleCompare() рассматривать два варианта одной и той же базовой буквы как одинаковыеесли у них разные акценты (как в третьем примере) выше.

Кроме того, вы можете использовать{ sensitivity: 'base' }, который обрабатывает два символа как эквивалентные, если их базовый символ одинаков (такA будет рассматриваться как эквивалентá).

Заметка что третий параметрlocaleCompare не поддерживается в IE10 или более ранних версиях или некоторых мобильных браузерах (см. таблицу совместимости на странице, указанной выше), поэтому, если вам требуется поддержка этих браузеров, вы 'понадобится какой-нибудь запасной вариант:

function ciEqualsInner(a, b) {
    return a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0;
}

function ciEquals(a, b) {
    if (typeof a !== 'string' || typeof b !== 'string') {
        return a === b;
    }

    //      v--- feature detection
    return ciEqualsInner('A', 'a')
        ? ciEqualsInner(a, b)
        : /*  fallback approach here  */;
}

Оригинальный ответ

Лучший способ сделать сравнение без учета регистра в JavaScript - это использовать RegExpmatch() метод сi флаг.

Поиск без учета регистра

Когда обе сравниваемые строки являются переменными (не константами), тогданемного сложнеепотому что вам нужно сгенерировать RegExp из строки, но передача строки в конструктор RegExp может привести к неправильным совпадениям или неудачным совпадениям, если в строке есть специальные символы регулярного выражения.

Если вы заботитесь о интернационализации, нет использоватьtoLowerCase() или жеtoUpperCase() как это не• обеспечить точное сравнение без учета регистра на всех языках.

http://www.i18nguy.com/unicode/turkish-i18n.html

 StingyJack19 мар. 2018 г., 02:53
я мог бы использовать localeCompare (), но его возвращение -1 для'a'.localeCompare('A') и как опера яищу строку без учета регистра. I '
 Samuel Neff06 июл. 2018 г., 06:46
@ Черт, я нене вижу большой ценности в разделении. Ключевым моментом является то, что это второй ответ в списке из-за голосов, и новые, и старые ответы намного лучше, чем принятый ответ. Это'Прискорбно, что иногда обучение на основе социальных сетей нена самом деле подтолкнуть правильный ответ к вершине.
 Samuel Neff12 окт. 2017 г., 19:20
@PeterandtheWolf Я поражен, сколько голосов и комментариев яЯ все еще получаю этот 7-летний ответ. Я отредактировал его сейчас, чтобы включить более современное и лучшее решение.
 Agoston Horvath01 апр. 2015 г., 13:30
Использование этого является наиболее дорогостоящим решением для сравнения строк без учета регистра. RegExp предназначен для сложного сопоставления с шаблоном, поэтому он должен построить дерево решений для каждого шаблона, а затем выполнить его для входных строк. В то время как это будет работать, это сравнимо с поездкой на реактивном самолете за покупками в следующем квартале. д-р, пожалуйста, несделать это
 rogerdpack23 сент. 2016 г., 06:59
Хотите добавить пример?
 Samuel Neff04 июл. 2018 г., 16:08
@ Спасибо за объяснения. Я бы неНе согласен, есть риск. К счастью, теперь есть намного лучшие варианты - вопросу 7 лет, и он по-прежнему получает много трафика и голосов. Я'Переместим редактирование / предупреждение в начало ответа.
 Sandip Ransing03 сент. 2013 г., 11:48
** не забудьте добавить^ в начале и$ в конце регулярного выражения, чтобы оно точно соответствовало.
 Stefan Steiger06 июн. 2014 г., 18:50
Неправильно, это нене работает, если строка содержит выражения регулярных выражений.
 JLRishe16 янв. 2019 г., 09:40
@SamuelNeff Я полагаю, что для какой-то функции поиска вы, вероятно, захотите игнорировать акценты, но для простого сравнения двух значений без учета регистра я бы хотел принять во внимание акценты, потому что, например, «añОперационные системы" а также "Anos» два совершенно разных слова. Я'Я не уверен, что является более распространенным, и яЯ думаю, это зависит от ситуации. То есть's проблема некоторых языков, которые пропускают акценты на заглавных буквах, так чтонемного гадости. FWIW, .NET 'Встроенное сравнение без учета регистра рассматривает акценты как существенные.
 NessDan24 июл. 2018 г., 19:34
ПровереноlocaleCompare и это'Удивительно, но, к сожалению, можно сравнивать только строки с начала, а не с середины (поэтому нечеткий поиск выбрасывается из окнаесли вы не хотите принять пакет NPM)
 Jasen25 сент. 2016 г., 22:17
преобразование строки в регулярное выражение довольно просто, просто$ впереди и^ впоследствии и \ перед всем ASCII в исходной строке, которая 'не является управляющим символом, пробелом или буквенно-цифровым символом.
 Samuel Neff11 янв. 2019 г., 18:31
@RLRishe спасибо за редактирование. Отличное дополнение. Я'Я удивлен, что вы бы порекомендовали чувствительностьaccent и неbase? Для сравнения нетне принято ли игнорировать акценты, так как при вводе данных для поиска люди часто их пропускают? Я понимаю, что это полностью зависит от контекста, просто любопытно, что обычно более распространено.
 Wyck03 июл. 2018 г., 21:56
m downvoting из-за дополнительной сложности и риска, связанного с дезинфекцией текста перед его переводом в регулярное выражение. Это само по себе мешает этому бытьлучший способ", Вероятность создания недопустимого регулярного выражения с помощью этой техники очень высока.
 Samuel Neff06 июн. 2014 г., 19:29
@ Неприятно, да, этоТо, что я сказал, должно быть обработано ... "вам нужно сгенерировать RegExp из строки, но передача строки в конструктор RegExp может привести к неправильным совпадениям или неудачным совпадениям, если в строке есть специальные символы регулярного выражения "
 Judah Gabriel Himango01 авг. 2018 г., 17:58
@StingyJack для сравнения без учета регистра с помощью localeCompare, вы должны сделать 'a'.localeCompare ( 'А', неопределенный, {чувствительность: 'база' })
 Wyck05 июл. 2018 г., 15:17
@SamuelNeff, не могли бы вы разделить хороший совет на новый ответ? Оригинальный ответ не велик (по причинам, которые яупомянул) но думаю совет использоватьlocaleCompare стоит отдельного ответа, потому что он радикально отличается от того, что предлагается в вашем первоначальном ответе. (Я понимаю этоМне тоже 7 лет, но цифры достаточно высоки, и кажется, что трафик все еще привлекает внимание.) Моя цель - убрать двустороннюю "раздвоение личности" этого ответа, за который сложно проголосовать. Примечание: @Jay предоставил ответ, который предлагает.localeCompare
 Peter and the Wolf12 окт. 2017 г., 17:15
Прости меня за небольшой комментарий, но я просто кричу процитировать классику: «Теперь у вас две проблемы ».

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

function my_strcasecmp( a, b ) 
{
    if((a+'').toLowerCase() > (b+'').toLowerCase()) return 1  
    if((a+'').toLowerCase() < (b+'').toLowerCase()) return -1
    return 0
}

Javascript, кажется, использует локаль "C" для сравнения строк, поэтому результирующее упорядочение будет некрасивым, если строки содержат не буквы ASCII. там'с этим мало что можно сделать, не проводя гораздо более детального осмотра строк.

Решение Вопроса

Самый простой способ сделать это (если выне беспокоиться о специальных символов Unicode) это позвонить:toUpperCase

var areEqual = string1.toUpperCase() === string2.toUpperCase();
 naspy97125 дек. 2018 г., 01:22
Это гений!
 Sven06 апр. 2018 г., 08:44
@Nateowami Хорошо, тогда у нас другое поведение в разных браузерных движках.
 Sebastian Mach26 янв. 2014 г., 09:02
@SLaks: Для нас, немецкого народа, однако,ß это неспециальный характер (но я понимаю, что вы имеете в виду;)).
 SLaks08 февр. 2015 г., 22:35
 SLaks28 мая 2014 г., 01:44
 fr34kyn0153522 сент. 2017 г., 11:17
Для JavaScript этот ответ кажется неправильным, "ß".toUpperCase () приводит к "SS»поэтому делает сравнение бесполезным.
 faressoft08 февр. 2015 г., 22:34
Что вы подразумеваете под "если ты'не беспокоиться о специальных символов Unicode " ? Какое влияние оказывает toUpperCase на эти символы?
 Sven12 янв. 2018 г., 10:07
@ fr34kyn01535 Этоне правда. "Ss".toUpperCase () приводит к "ß", Протестировано на браузере Edge и IE11. Также проверено на jsbin.com
 Stefan Steiger06 июн. 2014 г., 18:22
И БАМ! Мало того, что это не работает на международном уровне, это 's также предоставляет вам NullReferenceException;)
 Nateowami05 апр. 2018 г., 21:22
@Sven Только что протестировал в Firefox 59 и он вернулся "SS», То же самое в Node v8.9.4.
 Kugel26 июн. 2017 г., 16:59
Это действительно лучшее, что может предложить JS?
 SLaks26 янв. 2010 г., 17:22
@sam: я знаю. Тот'Вот почему я написал.if you're not worried about special Unicode characters
 Samuel Neff26 янв. 2010 г., 17:15
Преобразование в верхний или нижний регистр обеспечивает правильное сравнение без учета регистра на всех языках.i18nguy.com/unicode/turkish-i18n.html
 flybywire26 янв. 2010 г., 17:11
это достаточно хорошо для меня - но просто быть любопытным, как это не будет работать со специальными символами Unicode?
 Whiplash14 июн. 2018 г., 21:11
@ jpmc26 Эта публикация может ответить на ваш вопросstackoverflow.com/questions/26877514/... ... не должно быть никакой разницы.
 jpmc2627 мая 2014 г., 17:57
Есть ли причина предпочитатьtoUpperCase над ?toLowerCase
str = 'Lol', str2 = 'lOl', regex = new RegExp('^' + str + ', 'i');
if (regex.test(str)) {
    console.log("true");
}
 Qwertiy22 сент. 2017 г., 14:55
Регулярное выражение должно быть экранировано.

Как сказано в последних комментариях,string::localCompare поддерживает сравнение без учета регистра (среди других важных вещей).

Вот'простой пример

'xyz'.localeCompare('XyZ', undefined, { sensitivity: 'base' }); // returns 0

И универсальная функция, которую вы могли бы использовать

function equalsIgnoringCase(text, other) {
    text.localeCompare(other, undefined, { sensitivity: 'base' }) === 0;
}

Обратите внимание, что вместоundefined вам, вероятно, следует ввести конкретную локаль, с которой вы работаете. Это важно, как указано в документах MDN.

на шведском, ä и являются отдельными базовыми буквами

Варианты чувствительности

Поддержка браузера

На момент публикации UC Browser для Android и Opera Miniне делайте служба поддержкиместо действия а такжеопции параметры. пожалуйста, проверьтеhttps://caniuse.com/#search=localeCompare для актуальной информации.

 jay21 мая 2019 г., 08:57

Недавно я создал микробиблиотеку, которая предоставляет регистронезависимые помощники строк:https://github.com/nickuraltsev/ignore-case, (Оно используетtoUpperCase внутренне.)

var ignoreCase = require('ignore-case');

ignoreCase.equals('FOO', 'Foo'); // => true
ignoreCase.startsWith('foobar', 'FOO'); // => true
ignoreCase.endsWith('foobar', 'BaR'); // => true
ignoreCase.includes('AbCd', 'c'); // => true
ignoreCase.indexOf('AbCd', 'c'); // => 2

Существует два способа сравнения без учета регистра:

Преобразуйте строки в верхний регистр, а затем сравните их, используя строгий оператор (===). Как строгий оператор относится к операндам, прочитанным в:http://www.thesstech.com/javascript/relational-logical-operatorsСопоставление с шаблоном с использованием строковых методов:

Использовать "поиск" строковый метод для поиска без учета регистра. Читайте о поиске и других строковых методах по адресу:http://www.thesstech.com/pattern-matching-using-string-methods


  
    
      

        // 1st way

        var a = "apple";
        var b = "APPLE";  
        if (a.toUpperCase() === b.toUpperCase()) {
          alert("equal");
        }

        //2nd way

        var a = " Null and void";
        document.write(a.search(/null/i)); 

      
    

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

function compareStrings (string1, string2, ignoreCase, useLocale) {
    if (ignoreCase) {
        if (useLocale) {
            string1 = string1.toLocaleLowerCase();
            string2 = string2.toLocaleLowerCase();
        }
        else {
            string1 = string1.toLowerCase();
            string2 = string2.toLowerCase();
        }
    }

    return string1 === string2;
}
 Shital Shah20 нояб. 2018 г., 20:15
Функция в ответе ведет себя правильно:jsbin.com/bebifehafu/edit?html,output
 Celos28 мар. 2014 г., 14:52
Есть ли причина, по которой вы используете!!» выполнить явное логическое преобразование, вместо того чтобы позволить условию if оценивать достоверность значений?
 Sergey19 нояб. 2018 г., 18:26
Это должно быть ответом. Я'реорганизовал @ShitalShah 'Идея и поставить здесь:stackoverflow.com/a/53379742/1844247
 Sergey20 нояб. 2018 г., 13:06
@thekodester в вашей функции есть ошибка. этоcompareStrings("", "") дамfalse несмотря на то, что строки равны.
 Shital Shah25 окт. 2016 г., 21:45
Я рад, что это было полезно. Нулевая == сравнение нуля однако спорно. Обычно он должен возвращать false, но во многих случаях может быть желательно вернуть true. С другой стороны, null == not_null всегда должен возвращать false, что и приведенный выше код.
 Shital Shah31 мар. 2014 г., 12:22
Это'не требуется. Я предполагаю, что у меня было это от моей другой версии более сложного кода. Я обновил ответ.
 Stefan Steiger06 июн. 2014 г., 18:51
Лучше, чем остальные примеры, но все равно выдает нулевую ссылку.

С помощью регулярного выражения также мы можем достичь.

(/keyword/i).test(source)

/i для игнорирования дела. Если в этом нет необходимости, мы можем проигнорировать и проверить на НЕ совпадение с учетом регистра, например

(/keyword/).test(source)
 S.Serpooshan06 февр. 2019 г., 07:07
Это не отвечаетравенство проверьте (без учета регистра), как указано в вопросе! Но этоСодержит проверять! Дон»не использовать это
 Elmer25 окт. 2017 г., 12:25
Использование такого регулярного выражения будет соответствовать подстрокам! В вашем примере строкаkeyWORD приведет к положительному совпадению. Но строкаthis is a keyword yo или жеkeywords также приведет к положительному совпадению. Помните об этом :-)
 JHH10 мая 2019 г., 10:08
Конечно, чтобы соответствовать всей строке, регулярное выражение может быть изменено на/^keyword$/.test(source), но 1) еслиkeyword не константа, тынужно сделатьnew RegExp('^' + x + '$').test(source) и 2) использование регулярного выражения для проверки чего-либо столь простого, как равенство строк без учета регистра, совсем не очень эффективно.

Я написал расширение. очень тривиально

if (typeof String.prototype.isEqual!= 'function') {
    String.prototype.isEqual = function (str){
        return this.toUpperCase()==str.toUpperCase();
     };
}
 jt00029 июл. 2014 г., 14:45
@KhanSharp Многие люди считают анти-паттерном модифицировать прототип встроенных типов. Вот почему люди могут не голосовать за ваш ответ.
 Ryan Cavanaugh21 сент. 2013 г., 00:15
Что происходит, когда две кодовые базы с разными представлениями о том, как должен работать String # isEqual, пытаются существовать одновременно?
 m1.17 окт. 2015 г., 01:38
а что еслиstr передается в ноль?
 KhanSharp21 сент. 2013 г., 01:22
Два не могут существовать одновременно с одним и тем же именем. Если вы добавляете одно самостоятельно, вы можете либо изменить имя, либо проверить, существует ли другое. Если другой существует, вы можете использовать другой внутри своей реализации. Если оба исходят из двух разных библиотек, кто бы ни был последним, он должен работать сам. Если можете дать мне больше деталей, я могу иметь глубокий взгляд. (Мне любопытно, почему за мой ответ проголосовали?)
 Robert08 дек. 2014 г., 01:07
Isn»Не считается ли предпочтительным определение неизвестного метода? Например, как только какой-то браузер решит реализоватьString#isEqual или жеObject#isEqual изначально все ваши страницы ведут себя по-разному и могут делать странные вещи, если спецификация неТочно соответствует вашему.
 Eric Bishard23 авг. 2015 г., 07:35
Я думаю, что у Роберта есть правильная точка зрения. Прекрасная идея, но, возможно, соглашение об именах слишком обобщенное или слишком вероятное для использования в будущем спецификацией JavaScript. Может быть, все вы методы расширения могут бытьprototype.ksxIsEqual тогда, если вы захотите найти все свои расширения, у вас будет простой способ сделать это, и он, вероятно, никогда не будет конфликтовать.
 Triynko04 авг. 2017 г., 15:52
Многие считают анти-паттерн модифицировать прототип встроенных типов ». Тот'Слишком упрощение. Например, если метод родного прототипа запланирован или уже существует в современных браузерах, он 'S вполне допустимо, чтобы проверить его существование и "переопределение» это если этоее нет, если вы реализуете функцию, так что она ведет себя так же, как и нативная (т.е.регулировочная шайба»). Вы можете'просто посмотриNativeClass.prototype.nativeMethod = " и выкрикни OMG. Настоящая проблема здесь в том, что это неt как будет работать нативная реализация (то есть isEqual будет чувствительна к регистру).

Здесь много ответов, но мне нравится добавлять решение, основанное на расширении библиотеки String:

String.prototype.equalIgnoreCase = function(str)
{
    return (str != null 
            && typeof str === 'string'
            && this.toUpperCase() === str.toUpperCase());
}

Таким образом, вы можете использовать его так же, как в Java!

Пример:

var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
    document.write("a == b");
}
if (a.equalIgnoreCase(c)) {
    document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
    document.write("b != c");
}

Выход будет:

"a == b"
"b != c"

String.prototype.equalIgnoreCase = function(str) {
  return (str != null &&
    typeof str === 'string' &&
    this.toUpperCase() === str.toUpperCase());
}


var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
  document.write("a == b");
  document.write("<br>");
}
if (a.equalIgnoreCase(c)) {
  document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
  document.write("b != c");
}

Предположим, мы хотим найти строковую переменнуюneedle в строковой переменнойhaystack, Есть три ошибки:

Интернационализированные приложения должны избегатьstring.toUpperCase а такжеstring.toLowerCase, Используйте регулярное выражение, которое игнорирует регистр. Например,var needleRegExp = new RegExp(needle, "i"); с последующим .needleRegExp.test(haystack)В общем, вы можете не знать значениеneedle, Будьте осторожны, чтоneedle не содержит регулярных выраженийспециальные символы, Побег это, используя.needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");В других случаях, если вы хотите точно соответствоватьneedle а такжеhaystack, просто игнорируя регистр, обязательно добавьте"^" в начале и"$" в конце вашего конструктора регулярных выражений.

Принимая во внимание пункты (1) и (2), примером будет:

var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\
var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i");
var result = needleRegExp.test(haystack);
if (result) {
    // Your code here
}
amp;"), "i"); var result = needleRegExp.test(haystack); if (result) { // Your code here }
 HelpMeStackOverflowMyOnlyHope24 июл. 2016 г., 07:57
Можете ли вы предоставить добавить пример точного соответствия, игнорируя регистр. Вы описываете, как вы это делаете, но если кто-то неЯ не знаю, как разместить ^ и $.
 Chris Chute26 июл. 2016 г., 23:23
Вы держите пари! Все, что вам нужно сделать, это заменитьnew RegExp(...) часть в строке 3 со следующим:new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");, Это гарантирует отсутствие других символов до или после строки поиска.needle

Ваш ответ на вопрос