De beste manier om te zien of een item in een JavaScript-array staat?

Wat is de beste manier om erachter te komen of een object in een array staat?

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

Snippet uitvouwen


Antwoord 1, autoriteit 100%

Vanaf ECMAScript 2016 kunt u includes()

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. Daniel James‘s versie:

    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, autoriteit 28%

Als u jQuery gebruikt:

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

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


Antwoord 3, autoriteit 4%

Implementeer eerst indexOfin JavaScript voor browsers die het nog niet hebben. Zie bijvoorbeeld De array-extra’s van Erik Arvidsson(ook de bijbehorende blogpost). En dan kun je indexOfgebruiken zonder je zorgen te maken over browserondersteuning. Hier is een enigszins 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 gewijzigd om de lengte op te slaan, zodat het niet elke iteratie hoeft op te zoeken. Maar het verschil is niet enorm. Een functie voor minder algemene doeleinden is misschien sneller:

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 gebruik liever de standaardfunctie en laat dit soort micro-optimalisatie over voor wanneer het echt nodig is. Maar als je geïnteresseerd bent in micro-optimalisatie, heb ik de benchmarksaangepast die roosterononacid gekoppeld aan in de opmerkingen, naar benchmark zoeken in arrays. Ze zijn echter vrij grof, een volledig onderzoek zou arrays met verschillende typen, verschillende lengtes testen en objecten vinden die op verschillende plaatsen voorkomen.


Antwoord 4

Als de array ongesorteerd is, is er niet echt een betere manier (afgezien van het gebruik van de bovengenoemde indexOf, waarvan ik denk dat het op hetzelfde neerkomt). Als de array is gesorteerd, kunt u een binaire zoekopdracht uitvoeren, die als volgt werkt:

  1. Kies het middelste element van de array.
  2. Is het element dat je zoekt groter dan het element dat je hebt gekozen? Als dat zo is, heb je de onderste helft van de array geëlimineerd. Zo niet, dan heb je de bovenste helft uitgeschakeld.
  3. Kies het middelste element van de resterende helft van de array en ga verder zoals in stap 2, waarbij je de helften van de resterende array verwijdert. Uiteindelijk zul je ofwel je element vinden of geen array meer hebben om doorheen te kijken.

Binair zoeken loopt in de tijd evenredig met de logaritme van de lengte van de array, dus het kan veel sneller zijn dan naar elk afzonderlijk element te kijken.


Antwoord 5

[ ].has(obj)

ervan uitgaande dat .indexOf()is geïmplementeerd

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

!!! maak geen Array.prototype.has=function(){...omdat je in elke array een opsombaar element toevoegt en js wordt verbroken.

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

het gebruik van 2e arg (vlag) dwingt vergelijking op waarde in plaats van referentie

ruwe objecten vergelijken

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

Antwoord 6

Het hangt af van je doel. Als u voor het web programmeert, vermijd dan indexOf, het wordt niet ondersteund door Internet Explorer 6 (veel van hen worden nog steeds gebruikt!), of gebruik voorwaardelijk:

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

indexOfis waarschijnlijk gecodeerd in native code, dus het is sneller dan alles wat je kunt doen in JavaScript (behalve binair zoeken/dichotomie als de array geschikt is).
Opmerking: het is een kwestie van smaak, maar ik zou een return false;doen aan het einde van je routine, om een ​​echte Boolean te retourneren…


Antwoord 7

Hier is wat meta-kennis voor u – als u wilt weten wat u met een array kunt doen, raadpleeg dan de documentatie – hier is de array-pagina voor Mozilla

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

Daar zie je een verwijzing naar indexOf, toegevoegd in Javascript 1.6


Antwoord 8

Een robuuste manier om te controleren of een object een array in javascript is, wordt hier beschreven:

Hier zijn twee functies van het xa.jsframework dat ik koppel aan een utils = {}‘container’. Deze zouden u moeten helpen om arrays correct te detecteren.

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

Als je dan wilt controleren of een object in een array staat, zou ik ook deze code toevoegen:

/**
 * 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];
    };
}

En tot slot deze in_array-functie:

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

Other episodes