4952 Stimmen

Wie prüfe ich, ob ein Array einen Wert in JavaScript enthält?

Wie kann man am einfachsten und effizientesten herausfinden, ob ein JavaScript-Array einen Wert enthält?

Das ist die einzige Möglichkeit, die ich kenne:

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

Gibt es eine bessere und prägnantere Möglichkeit, dies zu erreichen?

65 Stimmen

Gerade getestet: Ihr Weg ist tatsächlich der schnellste für alle Browser: jsperf.com/find-element-in-obj-vs-array/2 (abgesehen von der Vorabspeicherung von a.length in einer Variablen), während die Verwendung von indexOf (wie in $.inArray) viel langsamer ist

23 Stimmen

Viele haben geantwortet, dass die Array#indexOf ist Ihre beste Wahl hier. Aber wenn Sie etwas wollen, das korrekt in Boolean umgewandelt werden kann, verwenden Sie dies: ~[1,2,3].indexOf(4) wird 0 zurückgeben, was als falsch ausgewertet wird, während ~[1,2,3].indexOf(3) wird -3 zurückgeben, was als wahr ausgewertet wird.

13 Stimmen

~ ist nicht das, was Sie für die Konvertierung in einen Booleschen Wert verwenden wollen, dafür brauchen Sie ! . Aber in diesem Fall wollen Sie die Gleichheit mit -1 prüfen, damit die Funktion nicht endet return [1,2,3].indexOf(3) === -1; ~ nicht binär ist, wird jedes Bit des Wertes einzeln invertiert.

21voto

Andru Luvisi Punkte 23151

Wenn Sie JavaScript 1.6 oder höher verwenden (Firefox 1.5 oder höher), können Sie Array.indexOf . Andernfalls, denke ich, werden Sie am Ende mit etwas ähnlich wie Ihr ursprünglicher Code.

20voto

cocco Punkte 15866

Eine hoffentlich schnellere bidirektionale indexOf / lastIndexOf alternativ

2015

Während die neue Methode includes ist sehr schön, aber die Unterstützung ist im Moment gleich Null.

Ich habe lange darüber nachgedacht, wie ich das langsame indexOf / lastIndexOf Funktionen.

Ein leistungsfähiger Weg wurde bereits gefunden, wenn man sich die wichtigsten Antworten ansieht. Von diesen wählte ich die contains Funktion von @Damir Zekic, die die schnellste sein sollte. Es heißt aber auch, dass die Benchmarks aus dem Jahr 2008 stammen und daher veraltet sind.

Ich bevorzuge auch while über for aber aus keinem bestimmten Grund habe ich die Funktion mit einer for-Schleife geschrieben. Man könnte es auch mit einer while -- .

Ich war neugierig, ob die Iteration war viel langsamer, wenn ich beide Seiten des Arrays überprüfen, während es tun. Offenbar nicht, und so ist diese Funktion etwa zwei Mal schneller als die oben genannten. Offensichtlich ist sie auch schneller als die native Funktion. Dies geschieht in einer realen Umgebung, in der man nie weiß, ob der gesuchte Wert am Anfang oder am Ende des Arrays liegt.

Wenn man weiß, dass man gerade ein Array mit einem Wert gepusht hat, bleibt die Verwendung von lastIndexOf wahrscheinlich die beste Lösung, aber wenn man durch große Arrays reisen muss und das Ergebnis überall sein könnte, könnte dies eine solide Lösung sein, um Dinge schneller zu machen.

Bidirektional indexOf / lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Leistungstest

https://jsbench.me/7el1b8dj80

Zu Testzwecken habe ich ein Array mit 100k Einträgen erstellt.

Drei Abfragen: am Anfang, in der Mitte und am Ende der Reihe.

Ich hoffe, Sie finden das auch interessant und testen die Leistung.

Anmerkung: Wie Sie sehen können, habe ich die contains Funktion, um die indexOf & lastIndexOf Ausgabe (also grundsätzlich true mit dem index y false con -1 ). Das sollte ihm nicht schaden.

Die Variante des Array-Prototyps

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

Die Funktion kann auch leicht geändert werden, um true oder false oder sogar das Objekt, den String oder was auch immer zurückzugeben.

Und hier ist die while Variante:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

Wie ist das möglich?

Ich denke, dass die einfache Berechnung, um den reflektierten Index in einem Array zu erhalten, so einfach ist, dass sie zwei Mal schneller ist als eine tatsächliche Schleifeniteration.

Hier ist ein komplexes Beispiel, bei dem drei Prüfungen pro Iteration durchgeführt werden, was aber nur mit einer längeren Berechnung möglich ist, die die Verlangsamung des Codes verursacht.

https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2

17voto

Lemex Punkte 3714
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Gibt den Array-Index zurück, wenn gefunden, oder -1, wenn nicht gefunden

16voto

Ztyx Punkte 12604

Wenn Sie wiederholt auf das Vorhandensein eines Objekts in einem Array prüfen, sollten Sie sich vielleicht mit

  1. Das Array bleibt immer sortiert, indem Einlegesortierung in Ihrem Array (neue Objekte an der richtigen Stelle einfügen)
  2. Aktualisieren von Objekten als Vorgang des Entfernens+sortierten Einfügens und
  3. Verwenden Sie eine binäre Suche Nachschlagen in Ihrem contains(a, obj) .

3 Stimmen

Oder wenn möglich, hören Sie ganz auf, ein Array zu verwenden, und verwenden Sie stattdessen ein Objekt als Wörterbuch, wie MattMcKnight und ninjagecko vorgeschlagen haben.

16voto

dr.dimitru Punkte 2557

Wir verwenden dieses Snippet (funktioniert mit Objekten, Arrays und Strings):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Verwendung:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X