Quel est le meilleur moyen de déterminer si un objet est dans un tableau?
C'est la meilleure façon que je connaisse:
function include(arr, obj) {
for(var i=0; i<arr.length; i++) {
if (arr[i] == obj) return true;
}
}
include([1,2,3,4], 3); // true
include([1,2,3,4], 6); // undefined
À partir de ECMAScript 2016, vous pouvez utiliser includes()
arr.includes(obj);
Si vous souhaitez prendre en charge IE ou d'autres navigateurs plus anciens:
function include(arr,obj) {
return (arr.indexOf(obj) != -1);
}
EDIT: Cela ne fonctionnera pas sur IE6, 7 ou 8 cependant. La meilleure solution consiste à définir vous-même s'il n'est pas présent:
Version de Mozilla (ECMA-262):
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
{
"use strict";
if (this === void 0 || 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 > 0)
{
n = Number(arguments[1]);
if (n !== n)
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
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;
};
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
version de roosteronacid :
Array.prototype.hasObject = (
!Array.indexOf ? function (o)
{
var l = this.length + 1;
while (l -= 1)
{
if (this[l - 1] === o)
{
return true;
}
}
return false;
} : function (o)
{
return (this.indexOf(o) !== -1);
}
);
Si vous utilisez jQuery:
$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);
Pour plus d'informations: http://api.jquery.com/jQuery.inArray/
Commencez par implémenter indexOf
en JavaScript pour les navigateurs qui ne l’ont pas déjà. Par exemple, voir extras de tableau d'Erik Arvidsson (également, le article de blog associé ). Et ensuite, vous pouvez utiliser indexOf
sans vous soucier de la prise en charge du navigateur. Voici une version légèrement optimisée de son implémentation indexOf
:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
Il a été modifié pour stocker la longueur afin qu'il ne soit pas nécessaire de la rechercher à chaque itération. Mais la différence n'est pas énorme. Une fonction moins générale pourrait être plus rapide:
var include = Array.prototype.indexOf ?
function(arr, obj) { return arr.indexOf(obj) !== -1; } :
function(arr, obj) {
for(var i = -1, j = arr.length; ++i < j;)
if(arr[i] === obj) return true;
return false;
};
Je préfère utiliser la fonction standard et laisser ce type de micro-optimisation au bon moment. Mais si vous êtes intéressé par la micro-optimisation, j'ai adapté benchmarks auquel le roosterononacide est lié dans les commentaires, à benchmark) (recherche dans les tableaux . Cependant, ils sont assez rudimentaires. Une enquête complète permettrait de tester des matrices de types différents, de longueurs différentes et de rechercher des objets situés à des endroits différents.
Si le tableau n'est pas trié, il n'y a pas vraiment de meilleur moyen (mis à part utiliser l'index mentionné ci-dessus, ce qui revient à la même chose, à mon avis). Si le tableau est trié, vous pouvez effectuer une recherche binaire, qui fonctionne comme suit:
La recherche binaire s'exécute dans le temps proportionnellement au logarithme de la longueur du tableau, de sorte qu'elle peut être beaucoup plus rapide que d'examiner chaque élément individuel.
[] .has (obj)
en supposant que .indexOf()
est implémenté
Object.defineProperty( Array.prototype,'has',
{
value:function(o, flag){
if (flag === undefined) {
return this.indexOf(o) !== -1;
} else { // only for raw js object
for(var v in this) {
if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
}
return false;
},
// writable:false,
// enumerable:false
})
!!! ne faites pas Array.prototype.has=function(){...
parce que vous allez ajouter un élément énumérable dans chaque tableau et que js est cassé.
//use like
[22 ,'a', {prop:'x'}].has(12) // false
["a","b"].has("a") // true
[1,{a:1}].has({a:1},1) // true
[1,{a:1}].has({a:1}) // false
l'utilisation de 2nd arg (flag) force la comparaison par valeur au lieu de référence
comparer des objets bruts
[o1].has(o2,true) // true if every level value is same
Cela dépend de votre but. Si vous programmez pour le Web, évitez indexOf
, Internet Explorer 6 ne le supporte pas (beaucoup d’entre eux sont encore utilisés!), Ou utilisez l’utilisation conditionnelle:
if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);
indexOf
est probablement codé en code natif, il est donc plus rapide que tout ce que vous pouvez faire en JavaScript (sauf recherche binaire/dichotomie si le tableau est approprié). Note: c'est une question de goût, mais je ferais un return false;
à la fin de votre routine, pour retourner un vrai booléen ...
Voici quelques méta-connaissances pour vous - si vous voulez savoir ce que vous pouvez faire avec un tableau, consultez la documentation - voici la page des tableaux pour Mozilla
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
Vous y verrez la référence à indexOf, ajoutée en Javascript 1.6
Un moyen robuste de vérifier si un objet est un tableau en javascript est détaillé ici:
Voici deux fonctions du cadre xa.js que j’attache à un utils = {}
‘conteneur’. Celles-ci devraient vous aider à détecter correctement les tableaux.
var utils = {};
/**
* utils.isArray
*
* Best guess if object is an array.
*/
utils.isArray = function(obj) {
// do an instanceof check first
if (obj instanceof Array) {
return true;
}
// then check for obvious falses
if (typeof obj !== 'object') {
return false;
}
if (utils.type(obj) === 'array') {
return true;
}
return false;
};
/**
* utils.type
*
* Attempt to ascertain actual object type.
*/
utils.type = function(obj) {
if (obj === null || typeof obj === 'undefined') {
return String (obj);
}
return Object.prototype.toString.call(obj)
.replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
};
Si vous voulez ensuite vérifier si un objet est dans un tableau, je voudrais également inclure ce code:
/**
* Adding hasOwnProperty method if needed.
*/
if (typeof Object.prototype.hasOwnProperty !== 'function') {
Object.prototype.hasOwnProperty = function (prop) {
var type = utils.type(this);
type = type.charAt(0).toUpperCase() + type.substr(1);
return this[prop] !== undefined
&& this[prop] !== window[type].prototype[prop];
};
}
Et enfin cette fonction in_array:
function in_array (needle, haystack, strict) {
var key;
if (strict) {
for (key in haystack) {
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] === needle) {
return true;
}
}
} else {
for (key in haystack) {
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] == needle) {
return true;
}
}
}
return false;
}