Містить регістр нечутливий


413

У мене є таке:

if (referrer.indexOf("Ral") == -1) { ... }

Те , що я хотів би зробити , це Ralвідчутно до регістру, так що це може бути RAl, rAlі т.д. , і по- , як і раніше збігаються.

Чи є спосіб сказати, що Ralце повинно бути нечутливим до регістру?


3
Думаю, що нечутливий до регексу випадок є більш елегантним рішенням, але кожен повинен пам’ятати про підводні камені створення RegExpбезпосередньо з інформацією користувача. Наприклад, користувач може ввести *і помилка буде викинута в RegExpконструктор. Прийняте рішення не має цієї проблеми.
pllee

Відповіді:


604

Додати .toLowerCase()після referrer. Цей метод перетворює рядок у нижній регістр. Потім використовуйте, .indexOf()використовуючи ralзамість Ral.

if (referrer.toLowerCase().indexOf("ral") === -1) { 

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

if (!/Ral/i.test(referrer)) {
   //    ^i = Ignore case flag for RegExp

16
Останній метод більш правильний; перший не вдасться до турецького я та будь-яких інших таких проблемних малих і малих пар: i18nguy.com/unicode/turkish-i18n.html
Domenic

23
Для турецьких було б краще використовувати toLocaleLowerCase()( ref )
Мотті

2
останній не відповідає на запитання, він говорить лише, якщо він є, а не отримати індекс відповідності. Або заголовок питання неправильний, або питання.
Маслоу

10
@Maslow Приклад питання стосувався тестування нечутливості випадку. Якщо ви хочете отримати індекс, використовуйте метод String.search :var index = referrer.search(/Ral/i);
Rob W

7
Додатковим ускладненням динамічного підходу до регулярних виразів є те, що якщо рядок пошуку, наприклад "Ral", містив спеціальні символи Regular Expression, такі як $. *? і т. д., у вас виникнуть проблеми, тому вам потрібно буде уникнути спеціальних символів, дивіться відповідь Майка Самуеля на це повідомлення: закінчується в JavaScript
zachelrath

94

Іншим варіантом є використання методу пошуку таким чином:

if (referrer.search(new RegExp("Ral", "i")) == -1) { ...

Це виглядає більш елегантно, ніж перетворення всієї струни в малі регістри, і це може бути більш ефективно.
У toLowerCase()коді є два пропуску по рядку, один пропуск є на всій рядку, щоб перетворити його в малі регістри, а інший - шукати потрібний індекс.
У RegExpкоді є один прохід по рядку, який, схоже, відповідає бажаному індексу.

Тому для довгих рядків я рекомендую використовувати RegExpверсію (я думаю, що для коротких рядків ця ефективність виникає за рахунок створення RegExpоб'єкта)


2
Це також трохи швидше на основі моїх тестів: jsperf.com/case-insensitive-indexof
Ілан

6
Станом на 2018.10.24, toLowerCase виграє з великим відривом у Chrome. toLowerCase (95,914,378 - ± 0,89% - найшвидший), індекс зворотного виразів (269,307 - ± 0,87% 100% повільніше)
nixkuroi

21

Використовуйте RegExp:

if (!/ral/i.test(referrer)) {
    ...
}

Або скористайтеся .toLowerCase():

if (referrer.toLowerCase().indexOf("ral") == -1)

1
+1, це потенційно може бути більш правильним, уникаючи «турецької проблеми я» та інші подібні підводні камені: i18nguy.com/unicode/turkish-i18n.html
Доменік

15

З ES2016 ви також можете використовувати трохи кращий / простіший / елегантніший метод (залежно від регістру):

if (referrer.includes("Ral")) { ... }

або (нечутливі до регістру):

if (referrer.toLowerCase().includes(someString.toLowerCase())) { ... }

Ось декілька порівнянь .indexOf()та .includes(): https://dev.to/adroitcoder/includes-vs-indexof-in-javascript


1
Я не думаю, що це включає чутливість до регістру
Kyle s

4
@Kyles includesвідрізняється від регістру в Chrome: спробуйте 'fooBar'.includes('bar')==>false
drzaus

10

Тут є кілька підходів.

Якщо ви хочете провести перевірку нечутливості до справ лише для цього примірника, зробіть щось на зразок наступного.

if (referrer.toLowerCase().indexOf("Ral".toLowerCase()) == -1) {
    ...

Крім того, якщо ви регулярно виконуєте цю перевірку, ви можете додати новий indexOf()подібний метод String, але зробити це нечутливим.

String.prototype.indexOfInsensitive = function (s, b) {
    return this.toLowerCase().indexOf(s.toLowerCase(), b);
}

// Then invoke it
if (referrer.indexOfInsensitive("Ral") == -1) { ...

1
definePropertyЯ пропоную для сучасних браузерів, які підтримують Object.defineProperty(String.prototype, 'indexOfInsensitive', {value: function(s,b){return this.toLowerCase().indexOf((s+'').toLowerCase(),b);}});. Два оновлення: явне перетворення рядків із використанням (s+'')циклу та без перерахунку у циклі ( for(var i in '') ... не відображається indexOfInsensitive.
Rob W

5
if (referrer.toUpperCase().indexOf("RAL") == -1) { ...

@Domenic: При всій повазі до турецької культури Туреччина повинна розглянути правописну реформу для спрощення цього аспекту. У Китаї було проведено ряд реформ щодо спрощення , а в Туреччині менше 10% населення Китаю та значно простіший алфавіт. Це можна зробити.
Дан Даскалеску


3

Приклад для будь-якої мови:

'My name is Хведор'.toLocaleLowerCase().includes('ХвЕдОр'.toLocaleLowerCase())

2

Це 2016 рік, і немає чіткого способу, як це зробити? Я сподівався на якісь копіпасти. Я поїду.

Примітки дизайну: Я хотів мінімізувати використання пам'яті, а отже, підвищити швидкість - щоб не було копіювання / мутування рядків. Я припускаю, що V8 (та інші двигуни) можуть оптимізувати цю функцію.

//TODO: Performance testing
String.prototype.naturalIndexOf = function(needle) {
    //TODO: guard conditions here

    var haystack = this; //You can replace `haystack` for `this` below but I wan't to make the algorithm more readable for the answer
    var needleIndex = 0;
    var foundAt = 0;
    for (var haystackIndex = 0; haystackIndex < haystack.length; haystackIndex++) {
        var needleCode = needle.charCodeAt(needleIndex);
        if (needleCode >= 65 && needleCode <= 90) needleCode += 32; //ToLower. I could have made this a function, but hopefully inline is faster and terser
        var haystackCode = haystack.charCodeAt(haystackIndex);
        if (haystackCode >= 65 && haystackCode <= 90) haystackCode += 32; //ToLower. I could have made this a function, but hopefully inline is faster and terser

        //TODO: code to detect unicode characters and fallback to toLowerCase - when > 128?
        //if (needleCode > 128 || haystackCode > 128) return haystack.toLocaleLowerCase().indexOf(needle.toLocaleLowerCase();
        if (haystackCode !== needleCode)
        {
            foundAt = haystackIndex;
            needleIndex = 0; //Start again
        }
        else
            needleIndex++;

        if (needleIndex == needle.length)
            return foundAt;
    }

    return -1;
}

Моя причина імені:

  • Повинен мати IndexOf у своєму імені
  • Не додайте суфікс - Of відноситься до наступного параметра
  • Не використовуйте "caseInsensitive", який довгий час
  • "природний" є хорошим кандидатом, тому що порівняння, яке враховує регістр за замовчуванням, не є для людини в першу чергу.

Чому ні...:

  • toLowerCase() - потенційні повторні дзвінки до toLowerCase в тій же строці.
  • RegExp- незручно шукати зі змінною. Навіть об’єкту RegExp незручно доводиться уникати символів

2
Настав 2016 рік, і ви все ще вважаєте, що англійська мова (або інші мови, що стосуються лише ASCII) - єдина мова у світі?
Roland Illig

3
@RolandIllig Ouch. Моя відповідь не відповідає іншим культурам, це недолік. Я б вітав будь-яке розуміння про розширення підтримки більшої кількості культур, світ є кращим місцем для співпрацівників.
Тодд

1

Для кращого пошуку використовуйте наступний код,

var myFav   = "javascript";
var theList = "VB.NET, C#, PHP, Python, JavaScript, and Ruby";

// Check for matches with the plain vanilla indexOf() method:
alert( theList.indexOf( myFav ) );

// Now check for matches in lower-cased strings:
alert( theList.toLowerCase().indexOf( myFav.toLowerCase() ) );

У першому сповіщенні () JavaScript повернув "-1" - інакше кажучи, indexOf () не знайшов відповідності: це просто тому, що "JavaScript" знаходиться в нижньому регістрі в першій строці і правильно написаний з великої літери у другій. Щоб здійснити нечутливий до регістру пошук з indexOf (), ви можете зробити обидва рядки або великими, або малими. Це означає, що, як і у другому сповіщенні (), JavaScript буде перевіряти лише наявність рядка, який ви шукаєте, а великі літери ігноруються.

Довідка, http://freewebdesigntutorials.com/javaScriptTutorials/jsStringObject/indexOfMethod.htm


1

Якщо referrerце масив, ви можете використовуватиfindIndex()

 if(referrer.findIndex(item => 'ral' === item.toLowerCase()) == -1) {...}

0

Ось мій прийом:

Сценарій :

var originalText = $("#textContainer").html()
$("#search").on('keyup', function () {
  $("#textContainer").html(originalText)
  var text = $("#textContainer").html()
  var val = $("#search").val()
  if(val=="") return;
  var matches = text.split(val)
  for(var i=0;i<matches.length-1;i++) {
    var ind =  matches[i].indexOf(val)
    var len = val.length
      matches[i] = matches[i] + "<span class='selected'>" + val + "</span>"
  }
  $("#textContainer").html(matches.join(""))

HTML:

<input type="text" id="search">
<div id="textContainer">
lorem ipsum is simply dummy text of the printing and typesetting industry. lorem ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of letraset sheets containing lorem ipsum passages, and more recently with desktop publishing software like Aldus pagemaker including versions of lorem ipsum.</div>

Codepen

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