Quelle est la manière la plus concise et la plus efficace de savoir si un tableau JavaScript contient une valeur?
C'est la seule façon que je connais de le faire:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Existe-t-il un moyen meilleur et plus concis pour y parvenir?
Ceci est très étroitement lié à la question Stack Overflow La meilleure façon de trouver un élément dans un tableau JavaScript? qui traite de la recherche d'objets dans un tableau à l'aide de indexOf
.
~[1,2,3].indexOf(4)
renverra 0 qui sera évalué comme faux, tandis que~[1,2,3].indexOf(3)
renverra -3 qui sera évalué comme vrai.~
n'est pas ce que vous voulez utiliser pour convertir en booléen, pour cela, vous en avez besoin!
. Mais dans ce cas, vous voulez vérifier l'égalité avec -1, de sorte que la fonction puisse se terminerreturn [1,2,3].indexOf(3) === -1;
~
n'est pas un binaire, elle inversera chaque bit de la valeur individuellement.[1,2,3].indexOf(4)
réellement -1 . Comme @mcfedr l'a souligné,~
est l' opérateur NOT au niveau du bit , voir ES5 11.4.8. Le fait est que, puisque la représentation binaire de se-1
compose uniquement de 1, son complément est0
, qui est évalué comme faux. Le complément de tout autre nombre sera non nul, donc vrai. Donc,~
fonctionne très bien et est souvent utilisé en conjonction avecindexOf
.[[1,2],[3,4]].includes([3,4])
?Réponses:
Les navigateurs modernes ont
Array#includes
, ce qui fait exactement cela et est largement pris en charge par tout le monde sauf IE:Vous pouvez également utiliser
Array#indexOf
ce qui est moins direct, mais ne nécessite pas de polyfills pour les navigateurs obsolètes.De nombreux frameworks proposent également des méthodes similaires:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
(également alias as_.include
et_.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(est_.contains
antérieure à 4.0.0)R.includes(value, array)
Notez que certains frameworks implémentent cela en tant que fonction, tandis que d'autres ajoutent la fonction au prototype de tableau.
la source
Array.include
qui renvoie un booléenarray.indexOf(object) != -1
inArray
est un nom terrible pour une fonction qui retourne l'index de l'élément, et-1
s'il n'existe pas. Je m'attendrais à ce qu'un booléen soit retourné.Mise à jour de 2019: cette réponse date de 2008 (11 ans!) Et n'est pas pertinente pour une utilisation JS moderne. L'amélioration des performances promise était basée sur une référence réalisée dans les navigateurs de l'époque. Il peut ne pas être pertinent pour les contextes d'exécution JS modernes. Si vous avez besoin d'une solution simple, cherchez d'autres réponses. Si vous avez besoin des meilleures performances, testez-vous par vous-même dans les environnements d'exécution pertinents.
Comme d'autres l'ont dit, l'itération à travers le tableau est probablement le meilleur moyen, mais il a été prouvé qu'une
while
boucle décroissante est le moyen le plus rapide d'itérer en JavaScript. Vous voudrez donc peut-être réécrire votre code comme suit:Bien sûr, vous pouvez également étendre le prototype Array:
Et maintenant, vous pouvez simplement utiliser ce qui suit:
la source
for (o in array)
qui ne devrait pas être fait lors de la boucle à travers le tableau en général ...indexOf
peut-être, mais c'est une "extension JavaScript de la norme ECMA-262; en tant que telle, elle peut ne pas être présente dans d'autres implémentations de la norme."Exemple:
AFAICS Microsoft n'offre pas d'alternative à cela, mais vous pouvez ajouter des fonctionnalités similaires aux tableaux dans Internet Explorer (et autres navigateurs qui ne prennent pas en charge
indexOf
) si vous le souhaitez, comme le révèle une recherche rapide sur Google (par exemple, celui-ci ).la source
ECMAScript 7 présente
Array.prototype.includes
.Il peut être utilisé comme ceci:
Il accepte également un deuxième argument facultatif
fromIndex
:Contrairement
indexOf
, qui utilise Strict Equality Comparison ,includes
compare à l'aide de l'algorithme d'égalité SameValueZero . Cela signifie que vous pouvez détecter si un tableau comprendNaN
:Contrairement à
indexOf
,includes
ne saute pas les indices manquants:Actuellement, il s'agit toujours d'un brouillon mais il peut être polyfilled pour le faire fonctionner sur tous les navigateurs.
la source
Les meilleures réponses supposent des types primitifs mais si vous voulez savoir si un tableau contient un objet avec un trait, Array.prototype.some () est une solution très élégante:
La bonne chose à ce sujet est que l'itération est abandonnée une fois que l'élément est trouvé, ce qui évite les cycles d'itération inutiles.
En outre, il s'intègre parfaitement dans une
if
instruction car il renvoie un booléen:* Comme l'a souligné jamess dans le commentaire, au moment de cette réponse, septembre 2018,
Array.prototype.some()
est entièrement pris en charge: table de support caniuse.comla source
Arrow functions
dans cet exemple, il n'est pas si bien pris en charge. Pour plus de détails, voir ici: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Disons que vous avez défini un tableau comme ceci:
Vous trouverez ci-dessous trois façons de vérifier s'il y
3
en a. Tous reviennent soittrue
oufalse
.Méthode Native Array (depuis ES2016) ( tableau de compatibilité )
Comme méthode de tableau personnalisé (avant ES2016)
Fonction simple
la source
Voici une implémentation compatible JavaScript 1.6 de
Array.indexOf
:la source
[].indexOf
est un raccourci pourArray.prototype.indexOf
. Nous, les programmeurs Javascript paranoïaques, évitons d'étendre à tout prix les prototypes natifs.[].indexOf
créer un nouveau tableau et y accéderindexOf
, alorsArray.prototype.indexOf
qu'il accède simplement au prototype directement?[].indexOf === Array.prototype.indexOf
(essayez-le dans FireBug), mais inversement[].indexOf !== Array.indexOf
.Utilisation:
la source
x ? true : false
est généralement redondant. C'est ici.array.indexOf(search) >= 0
est déjà un booléen. Justementreturn array.indexOf(search) >= 0
.L'extension de l'
Array
objet JavaScript est une très mauvaise idée car vous introduisez de nouvelles propriétés (vos méthodes personnalisées) dans desfor-in
boucles qui peuvent casser les scripts existants. Il y a quelques années, les auteurs de la bibliothèque Prototype ont dû repenser leur implémentation de bibliothèque pour supprimer ce genre de chose.Si vous n'avez pas à vous soucier de la compatibilité avec d'autres JavaScript exécutés sur votre page, allez-y, sinon, je recommanderais la solution de fonction autonome plus maladroite mais plus sûre.
la source
Bon mot:
la source
array.filter(e=>e==x).length > 0
est équivalentarray.some(e=>e==x)
maissome
plus efficaceEn sortant des sentiers battus pendant une seconde, si vous effectuez cet appel plusieurs fois, il est beaucoup plus efficace d'utiliser
un tableau associatifune carte pour effectuer des recherches à l'aide d'une fonction de hachage.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
la source
J'utilise ce qui suit:
la source
Array.prototype.some () a été ajouté à la norme ECMA-262 dans la 5e édition
la source
contains = (a, obj) => a.some((element) => element === obj))
Une solution bidirectionnelle
indexOf
/lastIndexOf
alternative, je l'espère, plus rapide2015
Bien que la nouvelle méthode inclut soit très agréable, le support est pratiquement nul pour l'instant.
Cela fait longtemps que je pensais à un moyen de remplacer les fonctions slow indexOf / lastIndexOf.
Un moyen performant a déjà été trouvé, en regardant les meilleures réponses. Parmi ceux que j'ai choisis
contains
Parmi fonction publiée par @Damir Zekic qui devrait être la plus rapide. Mais il indique également que les repères datent de 2008 et sont donc dépassés.Je préfère également
while
plusfor
, mais pour une raison non spécifique, j'ai fini d'écrire la fonction avec une boucle for. Cela pourrait aussi être fait avec unwhile --
.J'étais curieux de savoir si l'itération était beaucoup plus lente si je vérifiais les deux côtés du tableau en le faisant. Apparemment non, et donc cette fonction est environ deux fois plus rapide que les meilleures votées. Évidemment, il est également plus rapide que le natif. Ceci dans un environnement réel, où vous ne savez jamais si la valeur que vous recherchez est au début ou à la fin du tableau.
Lorsque vous savez que vous venez de pousser un tableau avec une valeur, l'utilisation de lastIndexOf reste probablement la meilleure solution, mais si vous devez parcourir de grands tableaux et que le résultat pourrait être partout, cela pourrait être une solution solide pour accélérer les choses.
IndexOf / lastIndexOf bidirectionnel
Test de performance
http://jsperf.com/bidirectionalindexof
Comme test, j'ai créé un tableau avec 100 000 entrées.
Trois requêtes: au début, au milieu et à la fin du tableau.
J'espère que vous trouverez également cela intéressant et testez les performances.
Remarque: Comme vous pouvez le voir, j'ai légèrement modifié la
contains
fonction pour refléter la sortie indexOf & lastIndexOf (donc en grostrue
avecindex
etfalse
avec-1
). Cela ne devrait pas lui nuire.La variante du prototype de matrice
La fonction peut également être facilement modifiée pour retourner vrai ou faux ou même l'objet, la chaîne ou quoi que ce soit.
Et voici la
while
variante:Comment est-ce possible?
Je pense que le calcul simple pour obtenir l'index réfléchi dans un tableau est si simple qu'il est deux fois plus rapide que de faire une itération de boucle réelle.
Voici un exemple complexe faisant trois vérifications par itération, mais cela n'est possible qu'avec un calcul plus long qui provoque le ralentissement du code.
http://jsperf.com/bidirectionalindexof/2
la source
Performance
Aujourd'hui 2020.01.07 j'effectue des tests sur MacOs HighSierra 10.13.6 sur Chrome v78.0.0, Safari v13.0.4 et Firefox v71.0.0 pour 15 solutions choisies. Conclusions
JSON
,Set
et étonnammentfind
(K, N, O) sont les plus lentes sur tous les navigateursincludes
(F) est rapide uniquement sur chromefor
(C, D) etindexOf
(G, H) sont assez rapides sur tous les navigateurs sur les petites et grandes baies, elles sont donc probablement le meilleur choix pour une solution efficacefor
(C, D, E) donnent des résultats similaires (~ 630 ops / sec - mais le E sur safari et firefox était 10- 20% plus lent que C et D)Résultats
Détails
J'exécute 2 cas de tests: pour tableau avec 10 éléments, et tableau avec 1 milion d'éléments. Dans les deux cas, nous mettons l'élément recherché au milieu du tableau.
Afficher l'extrait de code
Tableau petit - 10 éléments
Vous pouvez effectuer des tests sur votre machine ICI
Tableau grand - 1.000.000 éléments
Vous pouvez effectuer des tests sur votre machine ICI
la source
Si vous utilisez JavaScript 1.6 ou version ultérieure (Firefox 1.5 ou version ultérieure), vous pouvez utiliser Array.indexOf . Sinon, je pense que vous allez vous retrouver avec quelque chose de similaire à votre code d'origine.
la source
Renvoie l'index du tableau s'il est trouvé, ou -1 s'il n'est pas trouvé
la source
Nous utilisons cet extrait (fonctionne avec des objets, des tableaux, des chaînes):
Usage:
la source
Si vous vérifiez à plusieurs reprises l’existence d’un objet dans un tableau, vous devriez peut-être
contains(a, obj)
.la source
Solution qui fonctionne dans tous les navigateurs modernes:
Usage:
Solution IE6 +:
Usage:
Pourquoi utiliser
JSON.stringify
?Array.indexOf
etArray.includes
(ainsi que la plupart des réponses ici) ne comparent que par référence et non par valeur.Prime
Doublure ES6 non optimisée:
Remarque: La comparaison des objets par valeur fonctionnera mieux si les clés sont dans le même ordre, donc pour être sûr, vous pouvez d'abord trier les clés avec un package comme celui-ci: https://www.npmjs.com/package/sort-keys
Mise à jour de la
contains
fonction avec une optimisation de la performance. Merci itinance de l' avoir signalé.la source
includes
fonction avec votre suggestion. J'ai exécuté jsperf avec ma fonction. C'est environ 5 fois plus lent que les inclusions de lodash. Bien que lodash ne se compare pas en valeur et ne peut pas trouver{a: 1}
dans[{a: 1}]
. Je ne sais pas si une bibliothèque le fait. Mais je suis curieux de savoir s'il existe une manière plus performante et pas incroyablement complexe de le faire.contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
parce que les objets stringifiés maintiennent l'ordre des propriétés.sort-keys
note en basUtilisez lodash est une fonction.
Il est concis, précis et offre un excellent support multiplateforme.
La réponse acceptée ne répond même pas aux exigences.
Exigences: recommander le moyen le plus concis et le plus efficace pour savoir si un tableau JavaScript contient un objet.
Réponse acceptée:
Ma recommandation:
Remarques:
$ .inArray fonctionne très bien pour déterminer si une valeur scalaire existe dans un tableau de scalaires ...
... mais la question demande clairement un moyen efficace de déterminer si un objet est contenu dans un tableau.
Afin de gérer à la fois les scalaires et les objets, vous pouvez faire ceci:
la source
ECMAScript 6 a une proposition élégante à trouver.
Voici la documentation MDN à ce sujet.
La fonctionnalité de recherche fonctionne comme ceci.
Vous pouvez l'utiliser dans ECMAScript 5 et ci-dessous en définissant la fonction .
la source
Bien que ce
array.indexOf(x)!=-1
soit le moyen le plus concis de le faire (et qui est pris en charge par les navigateurs non Internet Explorer depuis plus de dix ans ...), ce n'est pas O (1), mais plutôt O (N), ce qui est terrible. Si votre tableau ne change pas, vous pouvez convertir votre tableau en table de hachage, puis faitestable[x]!==undefined
ou===undefined
:Démo:
(Malheureusement, bien que vous puissiez créer un tableau.prototype.contains pour «figer» un tableau et stocker une table de hachage dans this._cache sur deux lignes, cela donnerait des résultats erronés si vous choisissez de modifier votre tableau plus tard. JavaScript n'a pas suffisamment de crochets pour vous permet de conserver cet état, contrairement à Python par exemple.)
la source
On peut utiliser Set qui a la méthode "has ()":
la source
return proxy.has(obj)
c'est beaucoup plus propre que deux lignes avec une déclaration if-else icifunction contains(arr, obj) { return new Set(arr).has(obj); }
Utilisation:
Démo
Pour savoir exactement ce que le
tilde
~
faire à ce stade, reportez-vous à cette question Que fait un tilde quand il précède une expression? .la source
OK, vous pouvez simplement optimiser votre code pour obtenir le résultat!
Il existe de nombreuses façons de le faire qui sont plus propres et meilleures, mais je voulais juste obtenir votre modèle et l'appliquer à cela en utilisant
JSON.stringify
, faites simplement quelque chose comme ceci dans votre cas:la source
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
parce que les objets stringifiés maintiennent l'ordre des propriétés.En aucun cas le meilleur, mais je devenais juste créatif et ajoutais au répertoire.
Ne l'utilisez pas
la source
Surpris que cette question n'a toujours pas la dernière syntaxe ajoutée, ajoutant mes 2 cents.
Disons que nous avons un tableau d'objets arrObj et que nous voulons y rechercher obj.
Array.prototype. indexOf -> (renvoie index ou -1 ) est généralement utilisé pour trouver l'index de l'élément dans le tableau. Cela peut également être utilisé pour rechercher un objet mais ne fonctionne que si vous passez une référence au même objet.
Array.prototype. comprend -> (retourne vrai ou faux )
Array.prototype. find -> (prend le rappel, retourne la première valeur / objet qui retourne vrai dans CB).
Array.prototype. findIndex -> (prend le rappel, retourne l' index de la première valeur / objet qui retourne vrai dans CB).
Puisque find et findIndex prennent un rappel, nous pouvons extraire n'importe quel objet (même si nous n'avons pas la référence) du tableau en définissant de manière créative la vraie condition.
la source
Une solution simple pour cette exigence consiste à utiliser
find()
Si vous rencontrez un tableau d'objets comme ci-dessous,
Ensuite, vous pouvez vérifier si l'objet avec votre valeur est déjà présent ou non
si les données sont nulles, aucun administrateur, sinon, il retournera l'objet existant comme ci-dessous.
Ensuite, vous pouvez trouver l'index de cet objet dans le tableau et remplacer l'objet à l'aide du code ci-dessous.
vous obtiendrez de la valeur comme ci-dessous
j'espère que cela aidera n'importe qui.
la source
la source