Wyszukiwanie bez rozróżniania wielkości liter

272

Próbuję uzyskać wyszukiwanie bez rozróżniania wielkości liter z działającymi dwoma łańcuchami w JavaScript.

Normalnie byłoby tak:

var string="Stackoverflow is the BEST";
var result= string.search(/best/i);
alert(result);

/iFlaga byłaby dla wielkości liter.

Ale muszę szukać drugiego ciągu; bez flagi działa idealnie:

var string="Stackoverflow is the BEST";
var searchstring="best";
var result= string.search(searchstring);
alert(result);

Jeśli dodam /iflagę do powyższego przykładu, szukałby łańcucha wyszukiwania, a nie tego, co jest w zmiennej „łańcuch wyszukiwania” (kolejny przykład nie działa):

var string="Stackoverflow is the BEST";
var searchstring="best";
var result= string.search(/searchstring/i);
alert(result);

Jak mogę to osiągnąć?

Chris Boesing
źródło

Odpowiedzi:

373

Tak, użyj .matchraczej niż .search. Wynik .matchwywołania zwróci rzeczywisty ciąg znaków, który został dopasowany, ale nadal może być używany jako wartość logiczna.

var string = "Stackoverflow is the BEST";
var result = string.match(/best/i);
// result == 'BEST';

if (result){
    alert('Matched');
}

Używanie takiego wyrażenia regularnego jest prawdopodobnie najczystszym i najbardziej oczywistym sposobem na zrobienie tego w JavaScript, ale pamiętaj, że jest to wyrażenie regularne, a zatem może zawierać metaznaki regularne. Jeśli chcesz pobrać ciąg z innego miejsca (np. Dane wejściowe użytkownika) lub jeśli chcesz uniknąć ucieczki od wielu metaznaków, prawdopodobnie najlepiej użyć indexOftego w ten sposób:

matchString = 'best';
// If the match string is coming from user input you could do
// matchString = userInput.toLowerCase() here.

if (string.toLowerCase().indexOf(matchString) != -1){
    alert('Matched');
}
Dan
źródło
9
Przepraszam, jak możesz przekonwertować „najlepszy” na zmienną w pierwszym przykładzie? string.match(/best/i);
Doug Molineux
5
Dlaczego miałbyś używać .matchdo porównania wartości logicznych. Wyszukiwanie wykracza poza pierwszy wynik. Musisz zatrzymać się po pierwszym meczu, który .testlub .searchzrobisz. Sprawdź wydajność tutaj .
Rami
toLowerCasenajprawdopodobniej nie przejdzie testu Turcji ( moserware.com/2008/02/does-your-code-pass-turkey-test.html ) i podobnych problemów z konwersją spraw. Nie jestem pewien, jak ReGexsobie z tym poradzi, ale gdybym musiał zgadywać, powiedziałbym lepiej.
Ohad Schneider,
3
@DougMolineux można użyć konstruktora obiektów RegExp. var text = "best"; var exp = new RegExp(test, "i");. To jest to samo co /best/i.
Medeni Baykal
174

Zastąpić

var result= string.search(/searchstring/i);

z

var result= string.search(new RegExp(searchstring, "i"));
Siergiej Iliński
źródło
7
Jest to dość niechlujny sposób, ponieważ podejmuje kroki w celu ochrony przed nieoczekiwanymi metaznakami wyrażeń regularnych.
Dan.
35
Dan, wątpię, czy moja odpowiedź zasługuje na -1 od ciebie. Próbowałem pomóc ChrisBo, poprawiając jego nieprawidłowe użycie JavaScript, a mianowicie: var result = string.search (/ searchstring / i); do właściwego, w którym zmienna wyszukiwarka została użyta tak, jak zamierzał.
Sergey Ilinsky,
8
Dan ma rację (choć prawdopodobnie zamierzał powiedzieć „ brak miary”): s = 'a[b'; r = new RegExp(s)powoduje błąd składniowy (niezakończona klasa postaci)
glenn jackman
39

Jeśli szukasz tylko ciągu, a nie bardziej skomplikowanego wyrażenia regularnego, możesz użyć indexOf()- ale pamiętaj, aby najpierw napisać małe litery, ponieważ indexOf()rozróżnia małe i duże litery :

var string="Stackoverflow is the BEST"; 
var searchstring="best";

// lowercase both strings
var lcString=string.toLowerCase();
var lcSearchString=searchstring.toLowerCase();

var result = lcString.indexOf(lcSearchString)>=0;
alert(result);

Lub w jednym wierszu:

var result = string.toLowerCase().indexOf(searchstring.toLowerCase())>=0;
Odilon Redo
źródło
24

Załóżmy, że chcemy znaleźć zmienną needlełańcuchową w zmiennej łańcuchowej haystack. Istnieją trzy gotcha:

  1. Międzynarodowe aplikacje powinny unikać string.toUpperCasei string.toLowerCase. Zamiast tego użyj wyrażenia regularnego, które ignoruje wielkość liter. Na przykład, var needleRegExp = new RegExp(needle, "i");po którym następuje needleRegExp.test(haystack).
  2. Ogólnie rzecz biorąc, możesz nie znać wartości needle. Uważaj, aby needlenie zawierało żadnych znaków specjalnych wyrażeń regularnych . Ucieczka za pomocąneedle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); .
  3. W innych przypadkach, jeśli chcesz dokładnie dopasować needlei haystack, po prostu ignorując "^"wielkość liter, upewnij się, że dodajesz na początku i "$"na końcu konstruktora wyrażeń regularnych.

Biorąc pod uwagę punkty (1) i (2), przykładem może być:

var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i");
var result = needleRegExp.test(haystack);
alert(result);
Chris Chute
źródło
4

ES6 +:

let string="Stackoverflow is the BEST";
let searchstring="best";


let found = string.toLowerCase()
                  .includes(searchstring.toLowerCase());

includes()zwraca, truejeśli searchStringpojawia się na jednej lub kilku pozycjach lub w falseinny sposób.

Andrey
źródło
2

Jeśli martwisz się przypadkiem „niezakończonej klasy znaków”, pomocne byłoby usunięcie wszystkich znaków niealfanumerycznych:

searchstring = searchstring.replace (/ [^ a-zA-Z 0-9] + / g, '');
dsomnus
źródło
2

Podoba mi się odpowiedź @ CHR15TO, w przeciwieństwie do innych odpowiedzi, które widziałem na inne podobne pytania, ta odpowiedź faktycznie pokazuje, jak właściwie uciec od ciągu wyszukiwania podanego przez użytkownika (zamiast mówić, że byłoby to konieczne bez pokazywania, jak to zrobić).

Jednak nadal jest dość niezgrabny i prawdopodobnie stosunkowo wolniejszy. Dlaczego więc nie mieć konkretnego rozwiązania tego, co prawdopodobnie jest wspólnym wymogiem dla programistów? (A dlaczego nie uwzględnić go w ESW API BTW?)

Moja odpowiedź [ https://stackoverflow.com/a/38290557/887092] na podobne pytanie umożliwia:

var haystack = 'A. BAIL. Of. Hay.';
var needle = 'bail.';
var index = haystack.naturalIndexOf(needle);
Todd
źródło
1

Istnieją dwa sposoby porównywania bez rozróżniania wielkości liter:

  1. Konwertuj ciągi znaków na wielkie litery, a następnie porównuj je za pomocą ścisłego operatora ( ===). Jak surowy operator traktuje operandy czytać rzeczy na: http://www.thesstech.com/javascript/relational-logical-operators

  2. Dopasowywanie wzorców za pomocą metod łańcuchowych:

    Użyj metody „szukaj” w celu wyszukiwania bez rozróżniania wielkości liter. Przeczytaj o wyszukiwaniu i innych metodach ciągów na: http://www.thesstech.com/pattern-matching-using-string-methods

    <!doctype html>
      <html>
        <head>
          <script>
    
            // 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)); 
    
          </script>
        </head>
    </html>
Sohail Arif
źródło
1

Robię to często i używam prostego 5-liniowego prototypu, który akceptuje varargs. Jest szybki i działa wszędzie .

myString.containsIgnoreCase('red','orange','yellow')

/**
 * @param {...string} var_strings Strings to search for
 * @return {boolean} true if ANY of the arguments is contained in the string
 */
String.prototype.containsIgnoreCase = function(var_strings) {
  const thisLowerCase = this.toLowerCase()
  for (let i = 0; i < arguments.length; i++) {
    let needle = arguments[i]
    if (thisLowerCase.indexOf(needle.toLowerCase()) >= 0) {
      return true
    }
  }
  return false
}

/**
 * @param {...string} var_strings Strings to search for
 * @return {boolean} true if ALL of the arguments are contained in the string
 */
String.prototype.containsAllIgnoreCase = function(var_strings) {
  const thisLowerCase = this.toLowerCase()
  for (let i = 0; i < arguments.length; i++) {
    let needle = arguments[i]
    if (thisLowerCase.indexOf(needle.toLowerCase()) === -1) {
      return false
    }
  }
  return true
}

// Unit test

let content = `
FIRST SECOND
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."
FOO BAR
`

let data = [
  'foo',
  'Foo',
  'foobar',
  'barfoo',
  'first',
  'second'
]

let result
data.forEach(item => {
  console.log('Searching for', item)
  result = content.containsIgnoreCase(item)
  console.log(result ? 'Found' : 'Not Found')
})

console.log('Searching for', 'x, y, foo')
result = content.containsIgnoreCase('x', 'y', 'foo');
console.log(result ? 'Found' : 'Not Found')

console.log('Searching for all', 'foo, bar, foobar')
result = content.containsAllIgnoreCase('foo', 'bar', 'foobar');
console.log(result ? 'Found' : 'Not Found')

console.log('Searching for all', 'foo, bar')
result = content.containsAllIgnoreCase('foo', 'bar');
console.log(result ? 'Found' : 'Not Found')

Steven Spungin
źródło
0

Możesz zrobić wszystko małymi literami:

var string="Stackoverflow is the BEST";
var searchstring="best";
var result= (string.toLowerCase()).search((searchstring.toLowerCase()));
alert(result);
Robbert
źródło
-1

Zauważyłem, że jeśli użytkownik wpisze ciąg tekstu, ale opuści dane wejściowe bez wybrania którejkolwiek z opcji autouzupełniania, ukryta wartość wejściowa nie zostanie ustawiona, nawet jeśli ciąg znaków pokrywa się z jednym w tablicy. Tak więc przy pomocy innych odpowiedzi zrobiłem to:

var $local_source = [{
        value: 1,
        label: "c++"
    }, {
        value: 2,
        label: "java"
    }, {
        value: 3,
        label: "php"
    }, {
        value: 4,
        label: "coldfusion"
    }, {
        value: 5,
        label: "javascript"
    }, {
        value: 6,
        label: "asp"
    }, {
        value: 7,
        label: "ruby"
    }];
    $('#search-fld').autocomplete({
        source: $local_source,
        select: function (event, ui) {
            $("#search-fld").val(ui.item.label); // display the selected text
            $("#search-fldID").val(ui.item.value); // save selected id to hidden input
            return false;
        },
        change: function( event, ui ) {

            var isInArray = false;

            $local_source.forEach(function(element, index){

                if ($("#search-fld").val().toUpperCase() == element.label.toUpperCase()) {
                    isInArray = true;
                    $("#search-fld").val(element.label); // display the selected text
                    $("#search-fldID").val(element.value); // save selected id to hidden input
                    console.log('inarray: '+isInArray+' label: '+element.label+' value: '+element.value);
                };

            });

            if(!isInArray){

                $("#search-fld").val(''); // display the selected text
                $( "#search-fldID" ).val( ui.item? ui.item.value : 0 );

            }
        } 
Temu
źródło