Question La meilleure façon de trouver si un élément est dans un tableau JavaScript? [dupliquer]


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

Quelle est la meilleure façon de trouver 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

687
2017-09-27 15:41


origine


Réponses:


function include(arr,obj) {
    return (arr.indexOf(obj) != -1);
}

MODIFIER: Cela ne fonctionnera pas sur IE6, 7 ou 8 cependant. La meilleure solution consiste à le définir vous-même s'il n'est pas présent:

  1. Mozilla (ECMA-262) version:

      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 JamesLa version:

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

646
2017-09-27 15:45



Si vous utilisez jQuery:

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

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


203
2018-03-27 00:37



D'abord, mettre en œuvre indexOf en JavaScript pour les navigateurs qui ne l'ont pas déjà. Par exemple, voir Les bonus de tableau d'Erik Arvidsson (également article de blog associé). Et puis vous pouvez utiliser indexOf sans se soucier du support du navigateur. Voici une version légèrement optimisée de son indexOf la mise en oeuvre:

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 est changé pour stocker la longueur de sorte qu'il n'a pas besoin de le rechercher à chaque itération. Mais la différence n'est pas énorme. Une fonction moins générale peut ê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 pour quand c'est vraiment nécessaire. Mais si vous êtes intéressé par la micro-optimisation, j'ai adapté repères que le roosterononacid lié à dans les commentaires, à benchmark recherche dans les tableaux. Ils sont assez grossiers cependant, une enquête complète permettrait de tester des tableaux avec différents types, différentes longueurs et trouver des objets qui se produisent dans des endroits différents.


32
2017-09-27 18:10



Si le tableau n'est pas trié, il n'y a pas vraiment de meilleur moyen (mis à part l'indexOf mentionné ci-dessus, qui revient à la même chose). Si le tableau est trié, vous pouvez faire une recherche binaire, qui fonctionne comme ceci:

  1. Choisissez l'élément central du tableau.
  2. L'élément que vous recherchez est-il plus gros que l'élément que vous avez choisi? Si c'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. Finalement, vous trouverez votre élément ou vous n'avez plus 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 de regarder chaque élément individuel.


10
2017-09-27 15:50



en supposant .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 ajouterez 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 de 2nd arg (flag) force la comparaison par valeur au lieu de référence


9
2018-02-24 18:11



Cela dépend de votre objectif. Si vous programmez pour le Web, évitez indexOf, il n'est pas supporté par Internet Explorer 6 (beaucoup d'entre eux sont encore utilisés!), ou fait une utilisation conditionnelle:

if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);

indexOf est probablement codé en code natif, donc il est 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 ...


5
2017-09-27 16:28



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 Array pour Mozilla

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array

Là, vous verrez une référence à indexOf, ajouté en Javascript 1.6


4
2017-09-27 15:51



Un moyen robuste de vérifier si un objet est un tableau en javascript est détaillé ici:

Voici deux fonctions de la xa.js cadre que je joins à un utils = {} 'récipient'. Ceux-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 aussi 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;
}

3
2017-08-17 12:57