Подтвердить что ты не робот

Определите, есть ли строка в списке в JavaScript

В SQL мы можем видеть, есть ли строка в списке следующим образом:

Column IN ('a', 'b', 'c')

Какой хороший способ сделать это в JavaScript? Это так неуклюже, чтобы сделать это:

if (expression1 || expression2 || str === 'a' || str === 'b' || str === 'c') {
   // do something
}

И я не уверен насчет производительности или ясности этого:

if (expression1 || expression2 || {a:1, b:1, c:1}[str]) {
   // do something
}

Или можно использовать функцию переключения:

var str = 'a',
   flag = false;

switch (str) {
   case 'a':
   case 'b':
   case 'c':
      flag = true;
   default:
}

if (expression1 || expression2 || flag) {
   // do something
}

Но это ужасный беспорядок. Есть идеи?

В этом случае я должен использовать Internet Explorer 7 как страницу корпоративной интрасети. Так что ['a', 'b', 'c'].indexOf(str) !== -1 не будет работать изначально без некоторого синтаксического сахара.

4b9b3361

Ответ 1

EcmaScript 6

Если вы используете ES6, вы можете создать массив элементов, а также использование includes в includes:

['a', 'b', 'c'].includes('b')

Это имеет некоторые неотъемлемые преимущества по сравнению с indexOf потому что он может правильно проверять наличие NaN в списке и может сопоставлять отсутствующие элементы массива, такие как средний в [1,, 2] с undefined. includes также работы с типизированными массивами JavaScript, такими как Uint8Array.

Без массива

Вы можете добавить новое свойство isInList в строки следующим образом:

if (!String.prototype.isInList) {
   String.prototype.isInList = function() {
      let value = this.valueOf();
      for (let i = 0, l = arguments.length; i < l; i += 1) {
         if (arguments[i] === value) return true;
      }
      return false;
   }
}

Тогда используйте это так:

'fox'.isInList('weasel', 'fox', 'stoat') // true
'fox'.isInList('weasel', 'stoat') // false

Вы можете сделать то же самое для Number.prototype.

Array.indexOf

Если вы используете современный браузер, indexOf всегда работает. Однако для IE8 и более ранних версий вам понадобится полифилл.

Если indexOf возвращает -1, элемент отсутствует в списке. Однако помните, что этот метод не будет правильно проверять NaN, и хотя он может соответствовать явному undefined, он не может сопоставить отсутствующий элемент с undefined как в массиве [1,, 2].

Polyfill для indexOf в Internet Explorer 8 и более ранних indexOf или в любом другом браузере, в котором он отсутствует

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

В этой ситуации, когда мне нужно было найти решение для Internet Explorer 7, я "свернул свою" более простую версию функции indexOf() которая не соответствует стандартам:

if (!Array.prototype.indexOf) {
   Array.prototype.indexOf = function(item) {
      var i = this.length;
      while (i--) {
         if (this[i] === item) return i;
      }
      return -1;
   }
}

Однако я не думаю, что изменение Array.prototype - лучший ответ в долгосрочной перспективе. Модификация прототипов Object и Array в JavaScript может привести к серьезным ошибкам. Вам необходимо решить, насколько это безопасно в вашей среде. В первую очередь следует отметить, что повторение массива (когда Array.prototype имеет добавленные свойства) с for... in вернет имя новой функции в качестве одного из ключей:

Array.prototype.blah = function() { console.log('blah'); };
let arr = [1, 2, 3];
for (let x in arr) { console.log(x); }
// Result:
0
1
2
blah // Extra member iterated over!

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

Старый способ избежать этой поломки - во время перечисления проверять каждое значение, чтобы увидеть, действительно ли объект имеет его как не наследуемое свойство с if (arr.hasOwnProperty(x)) и только затем работать с этим x.

Новый способ ES6, чтобы избежать этого дополнительного ключа проблемы заключается в использовании of вместо in, for (let x of arr). Однако, если вы не можете гарантировать, что весь ваш код и сторонние библиотеки строго придерживаются этого метода, то для целей этого вопроса вы, вероятно, просто захотите использовать includes как указано выше.

Ответ 2

Вы можете вызвать indexOf:

if (['a', 'b', 'c'].indexOf(str) >= 0) {
    //do something
}

Ответ 3

В большинстве ответов предлагается метод Array.prototype.indexOf, единственная проблема в том, что он не будет работать ни в одной версии IE до IE9.

В качестве альтернативы я оставляю вам еще две опции, которые будут работать во всех браузерах:

if (/Foo|Bar|Baz/.test(str)) {
  // ...
}


if (str.match("Foo|Bar|Baz")) {
  // ...
}

Ответ 4

Массивы имеют метод indexOf, который можно использовать для поиска строк:

js> a = ['foo', 'bar', 'baz']
foo,bar,baz
js> a.indexOf('bar')
1
js> a.indexOf('quux')
-1

Ответ 5

Трюк, который я использовал,

>>> ("something" in {"a string":"", "somthing":"", "another string":""})
false
>>> ("something" in {"a string":"", "something":"", "another string":""})
true

Вы можете сделать что-то вроде

>>> a = ["a string", "something", "another string"];
>>> b = {};
>>> for(var i=0; i<a.length;i++){b[a[i]]="";} /* Transform the array in a dict */
>>> ("something" in b)
true

Ответ 6

Здесь моя:

String.prototype.inList=function(list){
    return (Array.apply(null, arguments).indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList('aaa','bbb','abc'))
    console.log('yes');
else
    console.log('no');

Это быстрее, если вы в порядке с передачей массива:

String.prototype.inList=function(list){
    return (list.indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList(['aaa','bbb','abc']))
    console.log('yes')

Здесь jsperf: http://jsperf.com/bmcgin-inlsit

Ответ 7

RegExp универсален, но я понимаю, что вы работаете с массивами. Итак, ознакомьтесь с этим подходом. Я использую его, и он очень эффективен и быстро вспыхивает!

var str = 'some string with a';
var list = ['a', 'b', 'c'];
var rx = new RegExp(list.join('|'));

rx.test(str);

Вы также можете применить некоторые изменения, то есть:

Однострочник

new RegExp(list.join('|')).test(str);

Нечувствительность к регистру

var rx = new RegExp(list.join('|').concat('/i'));


И многие другие!

Ответ 8

В дополнение к indexOf (которые предлагали другие плакаты), использование прототипа Enumerable.include() может сделать это более аккуратным и краткий:

var list = ['a', 'b', 'c'];
if (list.include(str)) {
  // do stuff
}

Ответ 9

Похоже, вам нужно использовать функцию in_array.

jQuery → inArray

Прототип → Array.indexOf

Или посмотрите эти примеры, если вы не используете jQuery или Prototype:

Стилистическое примечание: переменные, названные thisthing thatthing, должны быть названы так, чтобы рассказать вам о том, что они содержат (существительное).

Ответ 10

Спасибо за вопрос и решение, используя метод Array.indexOf.

Я использовал код этого решения, чтобы создать функцию inList(), которая, IMO, упростит запись и очиститель чтения:

function inList(psString, psList) 
{
    var laList = psList.split(',');

    var i = laList.length;
    while (i--) {
        if (laList[i] === psString) return true;
    }
    return false;
}

ПРИМЕНЕНИЕ:

if (inList('Houston', 'LA,New York,Houston') {
  // THEN do something when your string is in the list
}

Ответ 11

Я удивлен, что никто не упомянул простую функцию, которая берет строку и список.

function in_list(needle, hay)
{
    var i, len;

    for (i = 0, len = hay.length; i < len; i++)
    {
        if (hay[i] == needle) { return true; }
    }

    return false;
}

var alist = ["test"];

console.log(in_list("test", alist));

Ответ 12

Мое решение приводит к синтаксису следующего вида:

// Checking to see if var 'column' is in array ['a', 'b', 'c']

if (column.isAmong(['a', 'b', 'c']) {
  // Do something
}

И я реализую это, расширяя базовый прототип объекта, например:

Object.prototype.isAmong = function (MyArray){
   for (var a=0; a<MyArray.length; a++) {
      if (this === MyArray[a]) { 
          return true;
      }
   }
   return false;
}

В качестве альтернативы мы можем назвать метод isInArray (но, вероятно, не inArray) или просто isIn.

Преимущества: Простая, простая и самодокументируемая.

Ответ 13

                var urllist = [];
                var p = null;
                for (var i = 0; i < spans.length - 1; i++) {
                    p = $(spans[i]).find('input').val();
                    if (urllist.indexOf(p) >= 0) {
                        growl.warning("input fields contains Duplicate Entries");
                        return;
                    }
                    urllist.push(p)
                };

Ответ 14

Упрощенная версия ответ SLaks также работает:

if ('abcdefghij'.indexOf(str) >= 0) {
    // Do something
}

.... Так как строки являются самими массивами.:)

При необходимости выполните функцию indexof для Internet Explorer, как описано выше.