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

StackOverflow https://stackoverflow.com/questions/143847

  •  02-07-2019
  •  | 
  •  

Question

    

Cette question a déjà une réponse ici:

         

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
Était-ce utile?

La solution

A partir de ECMAScript 2016, vous pouvez utiliser < code> 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. 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. acide roosteronacide version:

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

Autres conseils

Si vous utilisez jQuery:

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

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

D'abord, implémentez indexOf en JavaScript pour les navigateurs qui ne l'ont pas déjà. Par exemple, consultez les les extras de tableau d'Erik Arvidsson (ainsi que l'élément 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'elle n'ait pas besoin 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 moment opportun. Mais si vous aimez la micro-optimisation, j'ai adapté les tests de performance qui roosterononacid associé aux commentaires, à la recherche de références dans des tableaux . Cependant, ils sont plutôt crus, une enquête complète permettrait de tester des matrices avec différents types, différentes longueurs et de trouver des objets qui se produisent à différents endroits.

Si le tableau n'est pas trié, il n'y a pas vraiment de meilleur moyen (mis à part l'utilisation de l'index mentionné ci-dessus, ce qui revient, selon moi, à la même chose). 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. Choisissez l'élément central de la moitié restante du tableau et continuez 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.

[] .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 () {... car vous allez ajouter un élément énumérable dans chaque tableau et 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 du deuxième argument force la comparaison par valeur au lieu de référence

comparaison d'objets bruts

[o1].has(o2,true) // true if every level value is same

Cela dépend de votre objectif. Si vous programmez pour le Web, évitez indexOf , il n'est pas pris en charge par Internet & nbsp; Explorer & nbsp; 6 (beaucoup d'entre eux sont encore utilisés!), Ou utilisez une 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 la recherche binaire / dichotomie si le tableau est approprié). Remarque: c’est une question de goût, mais je ferais un return false; à la fin de votre routine, pour renvoyer 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 / Référence / Global_Objects / Array

Vous y verrez une référence à indexOf, ajoutée en Javascript 1.6

Un moyen efficace 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 = {} & # 8216; conteneur & # 8217 ;. 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, j'inclurais également 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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top