Zawiera bez rozróżniania wielkości liter


413

Mam następujące:

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

Co lubię robić to, aby Ralwielkość liter ma znaczenie, tak że może być RAl, rAlitp i nadal pasuje.

Czy istnieje sposób, aby powiedzieć, że Ralmusi być rozróżniana wielkość liter?


3
Myślę, że regex bez uwzględniania wielkości liter jest bardziej eleganckim rozwiązaniem, ale każdy powinien pamiętać o pułapkach związanych z tworzeniem RegExpbezpośrednio na podstawie danych wprowadzonych przez użytkownika. Na przykład użytkownik może wprowadzić, *a konstruktor zgłosi błąd RegExp. Przyjęte rozwiązanie nie ma tego problemu.
pllee

Odpowiedzi:


604

Dodaj .toLowerCase()po referrer. Ta metoda zamienia ciąg znaków na ciąg małych liter. Następnie użyj .indexOf()za pomocą ralzamiast Ral.

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

To samo można również osiągnąć za pomocą wyrażenia regularnego (szczególnie przydatne, gdy chcesz przetestować wzorce dynamiczne):

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

16
Ta druga metoda jest bardziej poprawna; pierwszy nie powiedzie się w przypadku tureckiego I i innych takich problematycznych par wielkich i małych liter: i18nguy.com/unicode/turkish-i18n.html
Domenic

23
W przypadku tureckiego lepiej byłoby użyć toLocaleLowerCase()( ref )
Mottie

2
ten drugi nie odpowiada na pytanie, mówi tylko, jeśli tam jest, nie uzyskuje indeksu dopasowania. Albo tytuł pytania jest zły, albo pytanie.
Masłów

10
@Maslow Przykład pytania dotyczył testowania niewrażliwości na wielkość liter. Jeśli chcesz uzyskać indeks, skorzystaj z metody String.search :var index = referrer.search(/Ral/i);
Rob W

7
Dodatkową komplikacją dynamicznego podejścia do wyrażeń regularnych jest to, że jeśli szukany ciąg, np. „Ral”, zawiera znaki specjalne wyrażenia regularnego, takie jak $. *? itd., mielibyście problemy, więc musielibyście uciec od znaków specjalnych, zobacz odpowiedź Mike'a Samuela na ten post: kończy się w JavaScript
zachelrath

94

Inną opcją jest użycie metody wyszukiwania w następujący sposób:

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

Wygląda bardziej elegancko niż konwersja całego łańcucha na małe litery i może być bardziej wydajny.
Gdy toLowerCase()kod ma dwa przejścia nad ciągiem, jedno przejście znajduje się na całym ciągu, aby przekonwertować go na małe litery, a drugie na poszukiwanie pożądanego indeksu.
Z RegExpkodem wystarczy jedno przejście przez ciąg, który wygląda tak, aby pasował do pożądanego indeksu.

Dlatego na długich ciągach polecam używać RegExpwersji (wydaje mi się, że na krótkich ciągach ta wydajność zależy od utworzenia RegExpobiektu)


2
Jest to również trochę szybsze w oparciu o moje testy: jsperf.com/case-insensitive-indexof
Ilan Biala

6
Począwszy od 10.10.2018, toLowerCase wygrywa z dużym marginesem w Chrome. toLowerCase (95 914 378 - ± 0,89% - najszybszy), indeks regexO (269,307 - ± 0,87% 100% wolniej)
nixkuroi

21

Użyj RegExp:

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

Lub użyj .toLowerCase():

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

1
+1, mogłoby to potencjalnie być bardziej poprawne, unikając „problemu tureckiego I” i innych podobnych pułapek: i18nguy.com/unicode/turkish-i18n.html
Domenic

15

Od ES2016 możesz także zastosować nieco lepszą / łatwiejszą / bardziej elegancką metodę (z uwzględnieniem wielkości liter):

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

lub (bez rozróżniania wielkości liter):

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

Oto porównanie .indexOf()i .includes(): https://dev.to/adroitcoder/includes-vs-indexof-in-javascript


1
Nie sądzę, aby uwzględniono wielkość liter bez uwzględniania wielkości liter
Kyle,

4
@Kyles includesjest wielkość liter w Chrome: Spróbuj 'fooBar'.includes('bar')==>false
drzaus

10

Istnieje tutaj kilka podejść.

Jeśli chcesz wykonać rozróżnianie wielkości liter dla tylko tego wystąpienia, wykonaj następujące czynności:

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

Ewentualnie, jeśli przeprowadzasz tę kontrolę regularnie, możesz dodać do niej nową indexOf()metodę String, ale nie rozróżniaj wielkości liter.

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

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

1
definePropertyProponuję dla nowoczesnych przeglądarek, które obsługują Object.defineProperty(String.prototype, 'indexOfInsensitive', {value: function(s,b){return this.toLowerCase().indexOf((s+'').toLowerCase(),b);}});. Dwie aktualizacje: Jawna konwersja ciągu przy użyciu (s+'')i niepoliczalna w pętli ( for(var i in '') ... nie pokazuje indexOfInsensitive.
Rob W

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

@Domenic: Z całym szacunkiem dla kultury tureckiej Turcja powinna rozważyć reformę pisowni w celu uproszczenia tego aspektu. Chiny przeprowadziły wiele reform upraszczających , a Turcja ma mniej niż 10% populacji Chin i znacznie prostszy alfabet. To może być zrobione.
Dan Dascalescu


3

Przykład dla dowolnego języka:

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

2

Jest rok 2016 i nie ma jasnego sposobu, jak to zrobić? Miałem nadzieję na copypastę. Spróbuję.

Uwagi do projektu: Chciałem zminimalizować zużycie pamięci, a tym samym poprawić szybkość - aby nie było kopiowania / mutowania ciągów. Zakładam, że V8 (i inne silniki) mogą zoptymalizować tę funkcję.

//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;
}

Mój powód dla nazwy:

  • Powinien mieć w nazwie IndexOf
  • Nie dodawaj sufiksu - Of oznacza następujący parametr
  • Nie używaj „caseInsensitive”, który jest zbyt długi
  • „naturalny” jest dobrym kandydatem, ponieważ domyślne porównania z rozróżnianiem wielkości liter nie są naturalne dla ludzi.

Dlaczego nie...:

  • toLowerCase() - potencjalne powtarzające się wywołania toLowerCase na tym samym łańcuchu.
  • RegExp- niewygodne wyszukiwanie ze zmienną. Nawet obiekt RegExp jest niezręczny, gdy trzeba uciec od znaków

2
Jest rok 2016 i nadal uważasz, że angielski (lub inne języki tylko ASCII) jest jedynym językiem na świecie?
Roland Illig,

3
@RolandIllig Ouch. Moja odpowiedź nie uwzględnia innych kultur, to wada. Z chęcią przyjrzałbym się szerszemu wsparciu dla większej liczby kultur, świat jest lepszym miejscem dla współpracowników.
Todd

1

Aby przeprowadzić lepsze wyszukiwanie, użyj następującego kodu:

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() ) );

W pierwszym alertie () JavaScript zwrócił „-1” - innymi słowy, indexOf () nie znalazł dopasowania: dzieje się tak po prostu dlatego, że „JavaScript” jest zapisany małymi literami w pierwszym ciągu znaków, a odpowiednio dużymi literami w drugim. Aby wyszukiwać bez rozróżniania wielkości liter za pomocą indexOf (), możesz utworzyć oba ciągi wielkimi lub małymi literami. Oznacza to, że podobnie jak w drugim alertie () JavaScript będzie sprawdzał tylko występowanie szukanego ciągu, wielkie litery są ignorowane.

Odniesienie, http://freewebdesigntutorials.com/javaScriptTutorials/jsStringObject/indexOfMethod.htm


1

Jeśli referrerjest tablicą, możesz użyćfindIndex()

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

0

Oto moje zdanie:

Skrypt :

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.