Zoeken op website

Beste manier om te vinden of een item in een JavaScript-array zit?


Wat is de beste manier om te achterhalen of een object in een array zit?

Dit is de beste manier die ik ken:

function include(arr, obj) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == obj) return true;
  }
}

console.log(include([1, 2, 3, 4], 3)); // true
console.log(include([1, 2, 3, 4], 6)); // undefined

Antwoord #1

Vanaf ECMAScript 2016 kun je includes() gebruiken

arr.includes(obj);

Als je IE of andere oudere browsers wilt ondersteunen:

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

BEWERKEN: Dit werkt echter niet op IE6, 7 of 8. De beste oplossing is om het zelf te definiëren als het niet aanwezig is:

  1. Mozilla's (ECMA-262) versie:

       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. De versie van 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. roosteronacid's versie:

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

Antwoord #2

Als je jQuery gebruikt:

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

Voor meer informatie: http://api.jquery.com/jQuery.inArray/

Antwoord #3

Eerst implementeer je indexOf in JavaScript voor browsers die het nog niet hebben. Zie bijvoorbeeld Erik Arvidsson's array extras (en ook de bijbehorende blogpost). Dan kun je indexOf gebruiken zonder je zorgen te maken over browserondersteuning. Hier is een iets geoptimaliseerde versie van zijn indexOf implementatie:

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

Het is veranderd om de lengte op te slaan, zodat het niet bij elke iteratie hoeft te worden opgezocht. Maar het verschil is niet groot. Een minder algemene functie kan sneller zijn:

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

Ik geef de voorkeur aan het gebruik van de standaardfunctie en het overlaten van dit soort micro-optimalisatie voor wanneer het echt nodig is. Maar als je enthousiast bent over micro-optimalisatie, heb ik de benchmarks aangepast die roosterononacid in de reacties linkte, om het zoeken in arrays te benchmarken. Ze zijn echter vrij rudimentair, een volledige onderzoek zou arrays met verschillende typen, verschillende lengtes en het vinden van objecten die op verschillende plaatsen voorkomen testen.

Antwoord #4

Als de array niet gesorteerd is, is er eigenlijk geen betere manier (afgezien van het hierboven genoemde indexOf, wat volgens mij op hetzelfde neerkomt). Als de array gesorteerd is, kun je een binaire zoekopdracht doen, die als volgt werkt:

  1. Kies het middelste element van de array.
  2. Is het element waar je naar op zoek bent groter dan het element dat je hebt gekozen? Zo ja, dan heb je de onderste helft van de array geëlimineerd. Zo niet, dan heb je de bovenste helft geëlimineerd.
  3. Kies het middelste element van de overgebleven helft van de array en ga door zoals in stap 2, waarbij je helften van de overgebleven array wegvalt. Uiteindelijk zul je ofwel je element vinden of geen array meer hebben om door te zoeken.

Binaire zoekopdracht draait in een tijd die evenredig is aan de logaritme van de lengte van de array, dus het kan veel sneller zijn dan elk afzonderlijk element bekijken.

Gerelateerde artikelen