Регистронезависимый поиск

Я пытаюсь получить поиск без учета регистра с двумя строками в JavaScript.

обычно это было бы так:

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

на /i флаг будет для нечувствительных к регистру.

но мне нужно найти вторую строку; без флага он работает идеально:

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

если я добавлю /i флаг в приведенном выше примере он будет искать строку поиска, а не то, что находится в переменной "searchstring" (следующий пример не working):

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

как я могу этого достичь?

10 ответов


Да, использовать .match, а не .search. Результат от .match вызов вернет фактическую строку, которая была сопоставлена сама, но она все еще может использоваться как логическое значение.

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

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

использование регулярного выражения, как это, вероятно, самый аккуратный и самый очевидный способ сделать это в JavaScript, но имейте в виду это is регулярное выражение и, таким образом, может содержать метасимволы regex. Если вы хотите взять строку из другого места (например, пользовательский ввод), или если вы хотите, чтобы избежать того, чтобы избежать много метасимволов, то вы, вероятно, лучше всего использовать indexOf такой:

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');
}

заменить

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

С

var result= string.search(new RegExp(searchstring, "i"));

если вы просто ищете строку, а не более сложное регулярное выражение, Вы можете использовать indexOf() - но не забудьте сначала записать обе строки в нижнем регистре, потому что indexOf() регистр символов:

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

или в одной строке:

var result = string.toLowerCase().indexOf(searchstring.toLowerCase())>=0;

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

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

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

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

Мне нравится ответ @CHR15TO, в отличие от других ответов, которые я видел на других подобных вопросах, этот ответ фактически показывает, как правильно избежать строки поиска, предоставленной пользователем (а не говорить, что это было бы необходимо, не показывая, как).

однако он все еще довольно неуклюжий и, возможно, относительно медленный. Так почему бы не иметь конкретного решения того, что, вероятно, является общим требованием для кодеров? (И почему бы не включить его в API ES6 BTW?)

мой ответ [https://stackoverflow.com/a/38290557/887092] на аналогичный вопрос включает следующее:

var haystack = 'A. BAIL. Of. Hay.';
var needle = 'bail.';
var index = haystack.naturalIndexOf(needle);

ES6+:

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


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

includes() возвращает true Если searchString появляется в одной или нескольких позициях или false иначе.


Если вы обеспокоены случаем "unterminated character class", удаление всех не буквенно-цифровых символов было бы полезно:

searchstring = searchstring.replace(/[^a-zA-Z 0-9]+/g,'');

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

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

  2. сопоставление шаблонов с помощью строковых методов:

    используйте строковый метод "поиск" для поиска без учета регистра. Читайте о поиске и других string методы в: 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>
    

Я делаю это часто и используйте простой прототип 5 линий, который принимает varargs. Это быстро и работает везде.

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')

Я заметил, что если пользователь вводит строку текста, но оставляет вход без выбора каких-либо параметров автозаполнения, значение не устанавливается в скрытом входе, даже если строка совпадает с одной в массиве. Итак, с помощью других ответов я сделал следующее:

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

            }
        }