Quel est le moyen le plus concis et le plus efficace de savoir si un tableau JavaScript contient un objet?
C’est le seul moyen que je connaisse pour 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 plus efficace et plus concis d’y parvenir?
Ceci est très étroitement lié à la question de débordement de pile Le meilleur moyen de trouver un élément dans un tableau JavaScript? qui permet de rechercher des objets dans un tableau en utilisant indexOf
.
Les navigateurs actuels ont Array#includes
, ce qui fait exactement que, est largement pris en charge et comporte un polyfill pour les anciens navigateurs.
> ['joe', 'jane', 'mary'].includes('jane');
true
Vous pouvez également utiliser Array#indexOf
, qui est moins direct, mais ne nécessite pas Polyfills pour les navigateurs obsolètes.
jQuery propose $.inArray
, ce qui équivaut fonctionnellement à Array#indexOf
.
underscore.js , une bibliothèque d’utilitaires JavaScript, propose _.contains(list, value)
, alias _.include(list, value)
, tous deux utilisant indexOf en interne si un tableau JavaScript est passé.
Certains autres cadres offrent des méthodes similaires:
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
avant 4.0.0)array.includes(value)
Notez que certains frameworks l'implémentent en tant que fonction, tandis que d'autres l'ajoutent au prototype de tableau.
Mise à jour: Comme @orip le mentionne dans les commentaires, le repère lié a été défini en 2008, de sorte que les résultats peuvent ne pas être pertinents pour les navigateurs modernes. Cependant, vous en aurez probablement besoin pour prendre en charge des navigateurs non-modernes et ils n’ont probablement pas été mis à jour depuis. Toujours tester pour vous-même.
Comme d'autres l'ont déjà dit, l'itération à travers le tableau est probablement la meilleure solution, mais il { a été prouvé } _ qu'une boucle décroissante while
est le moyen le plus rapide d'itérer en JavaScript. Donc, vous voudrez peut-être réécrire votre code comme suit:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Bien entendu, vous pouvez également étendre le prototype Array:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
Et maintenant, vous pouvez simplement utiliser les éléments suivants:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
indexOf
peut-être, mais c'est une "extension JavaScript à la norme ECMA-262; en tant que telle, elle peut ne pas être présente dans d'autres implémentations de la norme."
Exemple:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft n'offre pas une sorte d'alternative à cela, mais vous pouvez ajouter une fonctionnalité similaire aux tableaux dans Internet Explorer (et d'autres navigateurs ne prenant pas en charge indexOf
) si vous le souhaitez. un la recherche rapide sur Google révèle } _ (par exemple, celui-ci ).
ECMAScript 7 introduit Array.prototype.includes
.
Il peut être utilisé comme ceci:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
Il accepte également un deuxième argument optionnel fromIndex
:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Contrairement à indexOf
, qui utilise Strict Equality Comparison , includes
compare à l'aide de SameValueZero algorithme d'égalité. Cela signifie que vous pouvez détecter si un tableau inclut une NaN
:
[1, 2, NaN].includes(NaN); // true
De même, contrairement à indexOf
, includes
n'ignore pas les index manquants:
new Array(5).includes(undefined); // true
Actuellement, il s'agit encore d'un brouillon, mais vous pouvez utiliser polyfilled pour le faire fonctionner sur tous les navigateurs.
b
est la valeur et a
est le tableau. Il retourne true
ou false
:
function(a, b) {
return a.indexOf(b) != -1
}
Voici une implémentation de JavaScript 1.6 compatible avec Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
Les premières 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:
const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
items.some(item => item.a === '3') // returns true
items.some(item => item.a === '4') // returns false
La bonne chose à ce sujet est que l’itération est abandonnée une fois que l’élément est trouvé, ainsi les cycles d’itération inutiles sont sauvegardés.
De plus, il s’intègre parfaitement dans une instruction if
car il renvoie un booléen:
if (items.some(item => item.a === '3')) {
// do something
}
* Comme l'a souligné jamess dans le commentaire, à compter d'aujourd'hui, septembre 2018, Array.prototype.some()
est entièrement pris en charge: Tableau de support caniuse.com
Utilisation:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
L'extension de l'objet Array
de JavaScript est une très mauvaise idée, car vous introduisez de nouvelles propriétés (vos méthodes personnalisées) dans les boucles for-in
, qui risquent de casser les scripts existants. Il y a quelques années, les auteurs de la bibliothèque Prototype ont dû repenser leur implémentation pour supprimer ce genre de choses.
Si vous n'avez pas à vous soucier de la compatibilité avec les autres scripts JavaScript en cours d'exécution sur votre page, n'hésitez pas, sinon, je vous conseillerais la solution de fonction autonome la plus délicate, mais la plus sûre.
Réfléchissez une seconde, si vous passez cet appel plusieurs fois, son utilisation est beaucoup plus efficace. un tableau associatif une carte pour faire des recherches en utilisant une fonction de hachage.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Bon mot:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
J'utilise les éléments suivants:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some () a été ajouté à la norme ECMA-262 dans la 5e édition
Une bidirectionnelle, espérons-le, plus rapide indexOf
/lastIndexOf
alternative
Alors que la nouvelle méthode includes est très agréable, le support est essentiellement nul pour le moment.
Cela faisait longtemps que je pensais au moyen de remplacer les fonctions lentes indexOf/lastIndexOf.
Un moyen performant a déjà été trouvé, en regardant les principales réponses. Parmi ceux-ci, j'ai choisi la fonction contains
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
à for
, mais pour une raison non précise, j'ai fini d'écrire la fonction avec une boucle for. Cela pourrait également être fait avec un while --
.
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 plus votés. Évidemment, c'est aussi plus rapide que le natif. Ceci dans un environnement réel, où vous ne savez jamais si la valeur que vous recherchez se trouve au début ou à la fin du tableau.
Quand vous savez que vous venez de pousser un tableau avec une valeur, lastIndexOf reste probablement la meilleure solution, mais si vous devez parcourir de grands tableaux et que le résultat risque d'être omniprésent, il peut s'agir d'une solution solide pour accélérer les choses.
Index bidirectionnel/lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
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 trouvez également cela intéressant et testez les performances.
Remarque: Comme vous pouvez le constater, j'ai légèrement modifié la fonction contains
pour refléter la sortie indexOf & lastIndexOf (donc, fondamentalement, true
avec index
et false
avec -1
). Cela ne devrait pas nuire.
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
La fonction peut également être facilement modifiée pour renvoyer true ou false, voire l’objet, la chaîne ou quoi que ce soit.
Et voici la variante while
:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
Je pense que le calcul simple pour obtenir l'index reflété 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 effectuant trois vérifications par itération, mais cela n’est possible qu’avec un calcul plus long qui entraîne le ralentissement du code.
Si vous vérifiez de manière répétée l'existence d'un objet dans un tableau, vous devriez peut-être examiner
contains(a, obj)
.Nous utilisons cet extrait (fonctionne avec des objets, des tableaux, des chaînes):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
Utilisation:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
Renvoie l'index d'un tableau s'il est trouvé ou -1 s'il n'est pas trouvé.
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.
Utilisez la fonction some de lodash.
Il est concis, précis et offre un excellent support multi-plateformes.
La réponse acceptée ne répond même pas aux exigences.
Requis: Recommandez le moyen le plus concis et le plus efficace de savoir si un tableau JavaScript contient un objet.
Réponse acceptée:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
Ma recommandation:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Remarques:
$ .inArray fonctionne bien pour déterminer si une valeur scalaire existe dans un tableau de scalaires ...
$.inArray(2, [1,2])
> 1
... mais la question demande clairement un moyen efficace de déterminer si un objet est contenu dans un tableau.
Pour gérer les scalaires et les objets, vous pouvez faire ceci:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
Solution qui fonctionne dans tous les navigateurs modernes:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
Solution IE6 +:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
JSON.stringify
?Array.indexOf
et Array.includes
(ainsi que la plupart des réponses ici) ne comparent que par référence et non par valeur.
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
ES6 one-liner non optimisé:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
Remarque: La comparaison d'objets par valeur fonctionnera mieux si les clés sont dans le même ordre. Par sécurité, vous pouvez donc trier les clés d'abord avec un package tel que celui-ci: https://www.npmjs.com/ package/sort-keys
Mise à jour de la fonction contains
avec une optimisation perf. Merci itinance pour le signaler.
array.indexOf(x)!=-1
est le moyen le plus concis de le faire (et est supporté par les navigateurs autres qu'Internet Explorer depuis plus de 10 ans ...), mais ce n'est pas O (1), mais plutôt O (N), ce qui est terrible. Si votre tableau ne changera pas, vous pouvez convertir votre tableau en table de hachage, puis faites table[x]!==undefined
ou ===undefined
:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
Démo:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(Malheureusement, bien que vous puissiez créer un Array.prototype.contains pour "geler" 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 ultérieurement. JavaScript ne possède pas de points d'ancrage suffisants pour laissez-vous garder cet état, contrairement à Python par exemple.)
ECMAScript 6 a une proposition élégante sur find.
La méthode find exécute la fonction de rappel une fois pour chaque élément présent dans le tableau jusqu'à ce qu'il en trouve un où le rappel renvoie un vrai valeur. Si un tel élément est trouvé, find renvoie immédiatement la valeur de cet élément. Sinon, find renvoie undefined. callback est invoqué uniquement pour les index du tableau ayant des valeurs assignées; il n'est pas appelé pour les index qui ont été supprimés ou qui n'ont jamais été assigné des valeurs.
Voici la documentation MDN à ce sujet.
La fonctionnalité de recherche fonctionne comme ceci.
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
Vous pouvez utiliser ceci dans ECMAScript 5 et inférieur pour en définissant la fonction .
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
Utilisation:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
Pour savoir exactement ce que la tilde
~
fait à ce stade, reportez-vous à cette question Que fait un tilde quand il précède une expression?.
Voici comment Le prototype le fait :
/**
* Array#indexOf(item[, offset = 0]) -> Number
* - item (?): A value that may or may not be in the array.
* - offset (Number): The number of initial items to skip before beginning the
* search.
*
* Returns the position of the first occurrence of `item` within the array — or
* `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
Voir aussi ici pour savoir comment ils l’accrochent.
Vous pouvez également utiliser cette astuce:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
OK, vous pouvez simplement optimiser votre code pour obtenir le résultat!
Il y a de nombreuses façons de le faire qui sont plus propres et meilleures, mais je voulais juste obtenir votre modèle et l'appliquer à l'aide de JSON.stringify
, faites simplement une chose comme celle-ci dans votre cas:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
Utilisation:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
Je sais que ce n'est pas la meilleure façon de faire, mais comme il n'y a pas de moyen IComparable natif d'interagir entre les objets, je suppose que c'est aussi proche que possible de comparer deux entités dans un tableau. Également, étendre un objet Array peut ne pas être une bonne chose à faire, mais parfois ça va (si vous en êtes conscient et le compromis).
On peut utiliser Set qui a la méthode "has ()":
function contains(arr, obj) {
var proxy = new Set(arr);
if (proxy.has(obj))
return true;
else
return false;
}
var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
Array.indexOf(Object)
. Array.includes(Object)
. Avec ECMA 6, vous pouvez utiliser Array.find(FunctionName)
où FunctionName
est une fonction définie par l'utilisateur pour rechercher l'objet dans le tableau.
J'espère que cela t'aides!
Comme d'autres l'ont mentionné, vous pouvez utiliser Array.indexOf
, mais il n'est pas disponible dans tous les navigateurs. Voici le code de https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf pour le rendre identique dans les navigateurs plus anciens.
indexOf est un ajout récent à la norme ECMA-262; en tant que tel, il peut ne pas être présent dans tous les navigateurs. Vous pouvez contourner ce problème en insérant le code suivant au début de vos scripts, permettant l’utilisation de indexOf dans les implémentations qui ne le supportent pas nativement. Ce L'algorithme est exactement celui spécifié dans ECMA-262, 5ème édition, en supposant que Object, TypeError, Number, Math.floor, Math.abs et Math.max ont leur valeur d'origine.
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
Surpris que la dernière syntaxe de cette question n’ait toujours pas été ajoutée, en ajoutant mes 2 centimes.
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 rechercher l'index d'un élément dans un tableau. Ceci peut également être utilisé pour rechercher un objet mais ne fonctionne que si vous passez une référence au même objet.
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
Array.prototype. inclut -> (retourne vrai ou faux )
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
Array.prototype. find -> (prend un callback, retourne en premier value/object qui renvoie true dans CB).
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
Array.prototype. findIndex -> (prend le rappel, retourne index de la première valeur/objet qui retourne vrai dans CB).
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
Puisque find et findIndex acceptent un rappel, nous pouvons extraire n'importe quel objet (même si nous n'avons pas la référence) d'un tableau en définissant de manière créative la vraie condition.
Ce n’est certes pas le meilleur, mais j’étais simplement créatif et j’ajoutais du répertoire.
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
J'ai regardé à travers les réponses soumises et j'ai compris qu'elles ne s'appliquent que si vous recherchez l'objet via une référence. Une recherche linéaire simple avec comparaison d'objet de référence.
Mais disons que vous n'avez pas la référence à un objet, comment allez-vous trouver le bon objet dans le tableau? Vous devrez aller linéairement et profondément comparer avec chaque objet. Imaginez si la liste est trop longue et que les objets qu'elle contient sont très grands et contiennent de gros morceaux de texte. Les performances chutent considérablement avec le nombre et la taille des éléments du tableau.
Vous pouvez stringifier les objets et les mettre dans la table de hachage native, mais vous aurez alors la redondance des données en vous rappelant que ces clés sont conservées car JavaScript les conserve pour 'for i in obj', et vous voulez seulement vérifier si l'objet existe ou non, c'est-à-dire , vous avez la clé.
Je pensais à cela pendant un certain temps en construisant un validateur JSON Schema et j'ai conçu un simple wrapper pour la table de hachage native, similaire à la mise en œuvre unique de la table de hachage, avec quelques exceptions d'optimisation que j'ai laissées à la table de hachage native. Il ne nécessite que des analyses comparatives des performances…. Tous les détails et le code sont disponibles sur mon blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a -large-array/ Je publierai bientôt les résultats des tests.
La solution complète fonctionne comme ceci:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
Si vous travaillez avec ES6 Vous pouvez utiliser un ensemble:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
Cela devrait être plus performant que n'importe quelle autre méthode
Ou cette solution:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
Une chose similaire: trouve le premier élément par un "search lambda":
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
Usage:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
Même chose en coffeescript:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
Je travaillais sur un projet pour lequel j'avais besoin d'une fonctionnalité telle que python set
qui supprime toutes les valeurs en double et renvoie une nouvelle liste. J'ai donc écrit cette fonction qui pourrait être utile à quelqu'un.
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.Push(arr[i]);
}
}
return res;
}
J'ai recommandé d'utiliser la bibliothèque de soulignement parce qu'elle renvoie la valeur et est prise en charge par tous les navigateurs.
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
Il a un paramètre: un tableau de nombres d'objets. Chaque objet du tableau a deux propriétés entières désignées par x et y. La fonction doit renvoyer un nombre de tous ces objets du tableau satisfaisant numbers.x == numbers.y
var numbers = [ { x: 1, y: 1 },
{ x: 2, y: 3 },
{ x: 3, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 } ];
count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
Utiliser idnexOf () est une bonne solution, mais vous devriez masquer la fonction d'indexation intégrée d'implémentation qui renvoie -1 avec l'opérateur ~:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
En plus de ce que d'autres ont dit, si vous n'avez pas de référence à l'objet que vous voulez chercher dans le tableau, vous pouvez faire quelque chose comme ça.
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
Array.some renvoie true si un élément correspond à la condition donnée et false si aucun des éléments ne correspond à la condition donnée.
Utilisation incluant la fonction javascript in-build
var optval = [];
optval.Push('A');
optval.Push('B');
optval.Push('C');
Nous pouvons rechercher la chaîne A dans le tableau javascript comme suit:
optval.includes('A') // =====> return true
Solution simple: ES6 Features " includes " method
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
function countArray(originalArray) {
var compressed = [];
// make a copy of the input array
var copyArray = originalArray.slice(0);
// first loop goes over every element
for (var i = 0; i < originalArray.length; i++) {
var count = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copyArray.length; w++) {
if (originalArray[i] == copyArray[w]) {
// increase amount of times duplicate is found
count++;
// sets item to undefined
delete copyArray[w];
}
}
if (count > 0) {
var a = new Object();
a.value = originalArray[i];
a.count = count;
compressed.Push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);