it-swarm.com.de

Der beste Weg, um herauszufinden, ob sich ein Element in einem JavaScript-Array befindet?

Was ist der beste Weg, um herauszufinden, ob sich ein Objekt in einem Array befindet?

Das ist der beste Weg, den ich kenne:

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

Ab ECMAScript 2016 können Sie includes() verwenden

arr.includes(obj);

Wenn Sie IE oder andere ältere Browser unterstützen möchten:

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

BEARBEITEN: Dies funktioniert jedoch nicht mit IE6, 7 oder 8. Die beste Lösung besteht darin, sie selbst zu definieren, wenn sie nicht vorhanden ist:

  1. Mozillas (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 James s 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. Roosteronacid s 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);
      }
    );
    
700
Vinko Vrsalovic

Wenn Sie jQuery verwenden:

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

Weitere Informationen: http://api.jquery.com/jQuery.inArray/

207
GerManson

Implementieren Sie zunächst indexOf in JavaScript für Browser, die es noch nicht haben. Siehe zum Beispiel Erik Arvidssons Array-Extras (auch zugehöriger Blog-Beitrag ). Und dann können Sie indexOf verwenden, ohne sich Gedanken über die Browserunterstützung machen zu müssen. Hier ist eine leicht optimierte Version seiner indexOf -Implementierung:

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

Es wurde geändert, um die Länge zu speichern, damit sie nicht bei jeder Iteration nachgeschlagen werden muss. Aber der Unterschied ist nicht groß. Eine weniger allgemeine Funktion ist möglicherweise schneller:

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

Ich bevorzuge es, die Standardfunktion zu verwenden und diese Art der Mikrooptimierung für den Fall zu belassen, dass sie wirklich benötigt wird. Aber wenn Sie auf Mikrooptimierung scharf sind, habe ich das Benchmarks , auf das Roosterononacid in den Kommentaren verweist, an Benchmarksuche in Arrays angepasst. Bei einer vollständigen Untersuchung würden Arrays mit unterschiedlichen Typen und Längen getestet und Objekte gefunden, die an unterschiedlichen Orten vorkommen.

33
Daniel James

Wenn das Array unsortiert ist, gibt es keinen wirklich besseren Weg (abgesehen von der Verwendung des oben erwähnten indexOf, was meiner Meinung nach dasselbe ist). Wenn das Array sortiert ist, können Sie eine binäre Suche durchführen, die folgendermaßen funktioniert:

  1. Wählen Sie das mittlere Element des Arrays.
  2. Ist das Element, das Sie suchen, größer als das Element, das Sie ausgewählt haben? In diesem Fall haben Sie die untere Hälfte des Arrays entfernt. Wenn nicht, haben Sie die obere Hälfte eliminiert.
  3. Wählen Sie das mittlere Element der verbleibenden Hälfte des Arrays aus und fahren Sie wie in Schritt 2 fort, wobei Sie die Hälften des verbleibenden Arrays entfernen. Irgendwann finden Sie entweder Ihr Element oder Sie haben kein Array mehr, durch das Sie schauen können.

Die binäre Suche wird in einer Zeit ausgeführt, die proportional zum Logarithmus der Länge des Arrays ist. Sie kann daher viel schneller sein, als die einzelnen Elemente zu betrachten.

11
assortedslog

[] .has (obj)

vorausgesetzt, .indexOf() ist implementiert

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

!!! Machen Sie nicht Array.prototype.has=function(){..., da Sie in jedem Array ein aufzählbares Element einfügen und js defekt ist.

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

die Verwendung von 2nd arg (flag) erzwingt einen Vergleich nach Wert anstelle einer Referenz

rohobjekte vergleichen

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

Es hängt von Ihrem Zweck ab. Wenn Sie für das Web programmieren, vermeiden Sie indexOf, es wird von Internet Explorer 6 nicht unterstützt (viele von ihnen werden noch verwendet!), Oder verwenden Sie es unter bestimmten Bedingungen:

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

indexOf ist wahrscheinlich in nativem Code codiert, daher ist es schneller als alles, was Sie in JavaScript tun können (mit Ausnahme der binären Suche/Dichotomie, wenn das Array geeignet ist). Hinweis: Es ist eine Frage des Geschmacks, aber ich würde am Ende Ihrer Routine einen return false; ausführen, um einen echten Booleschen Wert zurückzugeben ...

6
PhiLho

Hier sind einige Meta-Kenntnisse für Sie - wenn Sie wissen möchten, was Sie mit einem Array tun können, lesen Sie die Dokumentation - hier ist die Array-Seite für Mozilla

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

Dort sehen Sie einen Verweis auf indexOf, der in Javascript 1.6 hinzugefügt wurde

5
Paul Dixon

Eine zuverlässige Möglichkeit, um zu überprüfen, ob ein Objekt ein Array in Javascript ist, finden Sie hier:

Hier sind zwei Funktionen aus dem xa.js Framework, die ich an einen utils = {} "Container" anhänge. Diese sollten Ihnen helfen, Arrays richtig zu erkennen.

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

Wenn Sie dann überprüfen möchten, ob sich ein Objekt in einem Array befindet, würde ich auch diesen Code einfügen:

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

Und zum Schluss diese in_array-Funktion:

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