objekt - javascript variable auf inhalt prüfen




Wie überprüfe ich, ob ein Array ein Objekt in JavaScript enthält? (20)

Aktuelle Browser verfügen über Array#includes , Die genau das polyfill , werden weitgehend unterstützt und haben für ältere Browser eine polyfill .

> ['joe', 'jane', 'mary'].includes('jane');
true 

Sie können auch Array#indexOf , das weniger direkt ist, jedoch keine Polyfills für veraltete Browser erfordert.

jQuery bietet $.inArray , was funktionell äquivalent zu Array#indexOf .

Underscore.js , eine JavaScript-Dienstprogrammbibliothek, bietet _.contains(list, value) , den Alias _.include(list, value) . Beide verwenden indexOf intern, wenn ein JavaScript-Array übergeben wird.

Einige andere Frameworks bieten ähnliche Methoden an:

Beachten Sie, dass einige Frameworks dies als Funktion implementieren, während andere sie dem Array-Prototyp hinzufügen.

Wie kann ich am besten herausfinden, ob ein JavaScript-Array ein Objekt enthält?

Nur so weiß ich es zu tun:

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

Gibt es einen besseren und prägnanteren Weg, dies zu erreichen?

Dies ist sehr eng mit der Stack Overflow-Frage verbunden. Bester Weg, um ein Element in einem JavaScript-Array zu finden? welche das Finden von Objekten in einem Array mit indexOf .


Benutzen:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

Ich weiß, dass dies nicht der beste Weg ist, aber da es keine native IComparable Möglichkeit gibt, zwischen Objekten zu interagieren, denke ich, dass dies so nahe ist, wie Sie zwei Entitäten in einem Array vergleichen können. Das Erweitern eines Array-Objekts ist möglicherweise nicht sinnvoll, aber manchmal ist es in Ordnung (wenn Sie sich dessen und dem Kompromiss bewusst sind).



Das Erweitern des JavaScript- Array Objekts ist eine wirklich schlechte Idee, da Sie neue Eigenschaften (Ihre benutzerdefinierten Methoden) in for-in Schleifen einfügen, die vorhandene Skripts brechen können. Vor einigen Jahren mussten die Autoren der Prototype ihre Bibliotheksimplementierung überarbeiten, um nur solche Dinge zu entfernen.

Wenn Sie sich keine Gedanken über die Kompatibilität mit anderem JavaScript machen müssen, das auf Ihrer Seite ausgeführt wird, sollten Sie dies tun. Andernfalls würde ich die unbequemere, aber sicherere freistehende Funktionslösung empfehlen.


ECMAScript 6 hat einen eleganten Vorschlag zum Finden.

Die find-Methode führt die Callback-Funktion einmal für jedes im Array vorhandene Element aus, bis ein Element gefunden wird, bei dem Callback einen echten Wert zurückgibt. Wenn ein solches Element gefunden wird, gibt find sofort den Wert dieses Elements zurück. Andernfalls suchen Sie die Rückgabe undefined Callback wird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen wurden. Es wird nicht für Indizes aufgerufen, die gelöscht wurden oder denen noch nie Werte zugewiesen wurden.

Hier ist die MDN-Dokumentation dazu .

Die Suchfunktion funktioniert so.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

Sie können dies in ECMAScript 5 und nachfolgend verwenden, indem Sie die Funktion definieren .

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}

ECMAScript 7 führt array.includes(value) .

Es kann wie folgt verwendet werden:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

Es akzeptiert auch ein optionales zweites Argument fromIndex :

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

Im Gegensatz zu indexOf , das den Strict Equality Comparison verwendet , werden Vergleiche mit dem SameValueZero Equality-Algorithmus verwendet. Das bedeutet, dass Sie feststellen können, ob ein Array ein NaN :

[1, 2, NaN].includes(NaN); // true

Im Gegensatz zu indexOf werden fehlende Indizes nicht indexOf :

new Array(5).includes(undefined); // true

Derzeit ist es noch ein Entwurf, es kann jedoch mit polyfill , damit es in allen Browsern funktioniert.


Hier ist eine JavaScript 1.6-kompatible Implementierung von Array.indexOf :

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}

Ich benutze folgendes:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false

Man kann Set , das die Methode "has ()" hat:

function contains(arr, obj) {
  var proxy = new Set(arr);
  if (proxy.has(obj))
    return true;
  else
    return false;
}

var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));

Sie können diesen Trick auch verwenden:

var arrayContains = function(object) {
  return (serverList.filter(function(currentObject) {
    if (currentObject === object) {
      return currentObject
    }
    else {
      return false;
    }
  }).length > 0) ? true : false
}

Während array.indexOf(x)!=-1 der array.indexOf(x)!=-1 Weg ist, dies zu tun (und von Browsern, die kein Internet Explorer sind, über ein Jahrzehnt lang ...), ist es nicht O (1), sondern O ( N), was schrecklich ist. Wenn sich Ihr Array nicht ändert, können Sie Ihr Array in eine Hashtabelle konvertieren. Führen Sie dann die table[x]!==undefined oder ===undefined :

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

Demo:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(Sie können zwar ein Array.prototype.contains erstellen, um ein Array "einzufrieren" und eine Hashtable in this._cache in zwei Zeilen zu speichern, was jedoch zu falschen Ergebnissen führt, wenn Sie das Array später bearbeiten.) Lassen Sie diesen Status im Gegensatz zu Python zum Beispiel bei.)


Wenn Sie JavaScript 1.6 oder höher (Firefox 1.5 oder höher) verwenden, können Sie Array.indexOf verwenden . Ansonsten glaube ich, dass Sie am Ende etwas Ähnliches wie Ihren Originalcode erhalten.


Wenn Sie wiederholt prüfen, ob ein Objekt in einem Array vorhanden ist, sollten Sie dies vielleicht überprüfen

  1. Halten Sie das Array immer sortiert, indem Sie die Sortierung in Ihr Array einfügen (neue Objekte an der richtigen Stelle einfügen).
  2. Aktualisieren Sie Objekte wie Entfernen + Sortierte Einfügeoperation und
  3. Verwenden Sie eine binäre Suche in Ihrem contains(a, obj) .

Wir verwenden dieses Snippet (arbeitet mit Objekten, Arrays, 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
});

Verwendungszweck:

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

indexOf vielleicht, aber es ist eine "JavaScript-Erweiterung des ECMA-262-Standards; als solche ist sie möglicherweise in anderen Implementierungen des Standards nicht vorhanden."

Beispiel:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft bietet keine Alternative dazu. Sie können Arrays in Internet Explorer (und anderen Browsern, die indexOf nicht unterstützen) eine ähnliche Funktionalität hinzufügen, wenn Sie möchten, wie eine schnelle Google-Suche zeigt (z. B. dies) eins ).


b ist der Wert und a ist das Array. Es gibt true oder false :

function(a, b) {
    return a.indexOf(b) != -1
}

Update: Wie @orip in Kommentaren erwähnt, wurde der verknüpfte Benchmark 2008 durchgeführt, sodass die Ergebnisse für moderne Browser möglicherweise nicht relevant sind. Sie benötigen dies jedoch wahrscheinlich, um nicht moderne Browser zu unterstützen, und sie wurden wahrscheinlich seitdem nicht aktualisiert. Testen Sie immer für sich.

Wie andere bereits gesagt haben, ist die Iteration durch das Array wahrscheinlich der beste Weg, aber es hat sich gezeigt, dass eine abnehmende while Schleife der schnellste Weg ist, um in JavaScript zu iterieren. Vielleicht möchten Sie Ihren Code wie folgt umschreiben:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Natürlich können Sie auch den Array-Prototyp erweitern:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

Und jetzt können Sie einfach Folgendes verwenden:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

Auf keinen Fall das Beste, aber ich wurde gerade kreativ und fügte das Repertoire hinzu.

Verwenden Sie dies nicht

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));


Wie bereits erwähnt, können Sie verwenden Array.indexOf, aber es ist nicht in allen Browsern verfügbar. Hier ist der Code von https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf , damit er in älteren Browsern gleich funktioniert.

indexOf ist eine kürzlich erfolgte Erweiterung des ECMA-262-Standards. Als solches ist es möglicherweise nicht in allen Browsern vorhanden. Sie können dies umgehen, indem Sie den folgenden Code am Anfang Ihrer Skripts einfügen und indexOf in Implementierungen verwenden, die dies nicht systematisch unterstützen. Dieser Algorithmus ist genau der in ECMA-262, 5. Auflage, angegebene Algorithmus, vorausgesetzt, Object, TypeError, Number, Math.floor, Math.abs und Math.max haben ihren ursprünglichen Wert.

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (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 > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                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;
    }
}

function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() wurde in der 5. Ausgabe zum ECMA-262-Standard hinzugefügt







browser