web-dev-qa-db-fra.com

Déterminer si la chaîne est dans la liste en JavaScript

En SQL, nous pouvons voir si une chaîne est dans une liste comme ceci:

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

Quel est un bon moyen de faire cela en JavaScript? C'est tellement maladroit de faire ça:

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

Et je ne suis pas sûr de la performance ou de la clarté de ceci:

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

Ou on pourrait utiliser la fonction switch:

var str = 'a',
   flag = false;

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

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

Mais c'est un désordre horrible. Des idées?

Dans ce cas, je dois utiliser Internet Explorer 7 comme pour une page intranet d'entreprise. Donc, ['a', 'b', 'c'].indexOf(str) !== -1 ne fonctionnera pas en mode natif sans sucre de syntaxe.

191
ErikE

EcmaScript 6

Si vous utilisez ES6, vous pouvez construire un tableau des éléments et utiliser includes :

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

Ceci présente des avantages intrinsèques par rapport à indexOf, car il permet de tester correctement la présence de NaN dans la liste et de faire correspondre les éléments de tableau manquants tels que l'élément central dans [1, , 2] à undefined. includes fonctionne également sur Les tableaux typés en JavaScript tels que Uint8Array.

Sans tableau

Vous pouvez ajouter une nouvelle propriété isInList aux chaînes comme suit:

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

Alors utilisez-le comme suit:

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

Vous pouvez faire la même chose pour Number.prototype.

Array.indexOf

Si vous utilisez un navigateur moderne, indexOf fonctionne toujours. Cependant, pour IE8 et les versions antérieures, vous aurez besoin d'un polyfill.

Si indexOf renvoie -1, l'élément n'est pas dans la liste. Sachez cependant que cette méthode ne vérifie pas correctement NaN et qu’elle peut correspondre à une undefined explicite, elle ne peut pas associer un élément manquant à undefined comme dans le tableau [1, , 2].

Polyfill pour indexOf dans Internet Explorer 8 et versions antérieures, ou tout autre navigateur qui en manque

Vous pouvez toujours utiliser un polyfill personnalisé conforme aux normes pour que cela fonctionne dans les navigateurs plus anciens.

Dans cette situation où je devais créer une solution pour Internet Explorer 7, j'ai "lancé ma propre" version simplifiée de la fonction indexOf() qui n'est pas conforme aux normes:

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

Cependant, je ne pense pas que modifier Array.prototype soit la meilleure réponse à long terme. La modification de prototypes Object et Array en JavaScript peut entraîner de graves bogues. Vous devez décider si cela est sécurisé dans votre propre environnement. Il est à noter que l'itération d'un tableau (lorsque Array.prototype a ajouté des propriétés) avec for ... in renvoie le nouveau nom de la fonction sous la forme d'une des clés:

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!

Votre code fonctionne peut-être maintenant, mais dès que quelqu'un ajoute une bibliothèque ou un plugin JavaScript tiers qui ne protège pas avec zèle les clés héritées, tout peut casser.

L'ancien moyen d'éviter ce bris est, lors de l'énumération, de vérifier chaque valeur pour voir si l'objet l'a réellement comme propriété non héritée avec if (arr.hasOwnProperty(x)) et seulement alors travailler avec cette x.

La nouvelle méthode ES6 pour éviter ce problème extra-clé consiste à utiliser of au lieu de in, for (let x of arr). Toutefois, à moins que vous ne puissiez garantir que tout votre code et toutes les bibliothèques tierces respectent strictement cette méthode, vous voudrez probablement, pour les besoins de cette question, simplement utiliser includes comme indiqué ci-dessus.

110
ErikE

Vous pouvez appeler indexOf:

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

La plupart des réponses suggèrent la méthode Array.prototype.indexOf, le seul problème est que cela ne fonctionnera pas sur la version any IE antérieure à IE9.

Comme alternative, je vous laisse deux options supplémentaires qui fonctionneront sur tous les navigateurs:

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


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

Les tableaux ont une méthode indexOf qui peut être utilisée pour rechercher des chaînes:

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

Un truc que j'ai utilisé est

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

Vous pourriez faire quelque chose comme

>>> 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
11
Esteban Küber

Voilà le mien:

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

Celui-ci est plus rapide si vous êtes d'accord pour passer un tableau:

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

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

Voici le jsperf: http://jsperf.com/bmcgin-inlsit

8
Brian McGinity

RegExp est universel, mais je comprends que vous travaillez avec des tableaux. Alors, consultez cette approche. J'avais l'habitude de l'utiliser, et c'est très efficace et rapide!

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

rx.test(str);

Vous pouvez également appliquer quelques modifications, à savoir:

Bon mot

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

Insensible à la casse

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


Et plein d'autres!

6
sospedra

En plus de indexOf (ce que d’autres affiches ont suggéré), l’utilisation du prototype Enumerable.include () peut rendre ceci plus net et plus concis:

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

On dirait que vous devez utiliser la fonction in_array.

jQuery -> inArray 

Prototype -> Array.indexOf

Ou consultez ces exemples si vous n’utilisez pas jQuery ou Prototype:

Note stylistique:} _ Les variables nommées thisthing thatthing doivent être nommées pour vous dire quelque chose sur ce qu'elles contiennent (nom).

5
LG_PDX

Merci pour la question et la solution utilisant la méthode Array.indexOf.

J'ai utilisé le code de cette solution pour créer une fonction inList () qui simplifierait l'écriture et faciliterait la lecture:

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

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

USAGE:

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

Je suis surpris que personne n'ait mentionné une fonction simple qui prend une chaîne et une liste.

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));
0
Samuel Parkinson

Utilisation de indexOf (cela ne fonctionne pas avec IE8).

if (['Apple', 'cherry', 'orange', 'banana'].indexOf(value) >= 0) {
    // found
}

Pour supporter IE8, vous pouvez implémenter indexOf de Mozilla.

if (!Array.prototype.indexOf) {
    // indexOf polyfill code here
}

Expressions régulières via String.prototype.match (docs).

if (fruit.match(/^(banana|lemon|mango|pineapple)$/)) {

}
0
Tiago Medici

Ma solution donne une syntaxe comme celle-ci:

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

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

Et j'implémente cela en développant le prototype d'objet de base, comme ceci:

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

Nous pourrions également nommer la méthode isInArray (mais probablement pas inArray) ou simplement isIn.

Avantages: Simple, simple et auto-documenté.

0
John Hicks
                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)
                };
0
Akhil