web-dev-qa-db-fra.com

Meilleure façon de savoir si un élément est dans un tableau JavaScript?

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
753
zimbatm

À 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:

  1. 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;
      };
    
    }
    
  2. Version de Daniel James :

    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;
      };
    }
    
  3. 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);
      }
    );
    
700
Vinko Vrsalovic

Si vous utilisez jQuery:

$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);

Pour plus d'informations: http://api.jquery.com/jQuery.inArray/

207
GerManson

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.

33
Daniel James

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:

  1. Choisissez l'élément central du tableau.
  2. L'élément que vous recherchez est-il plus gros que celui que vous avez choisi? Si tel est le cas, vous avez éliminé la moitié inférieure du tableau. Si ce n'est pas le cas, vous avez éliminé la moitié supérieure.
  3. Sélectionnez l'élément central de la moitié restante du tableau et poursuivez comme à l'étape 2, en éliminant les moitiés du tableau restant. Vous finirez par trouver votre élément ou ne plus avoir de tableau à parcourir.

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.

11
assortedslog

[] .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
10
bortunac

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 ...

6
PhiLho

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

5
Paul Dixon

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;
}
4
Aaria Carter-Weir