Der beste Weg, um herauszufinden, ob ein Element in einem JavaScript-Array ist? [Duplikat]

StackOverflow https://stackoverflow.com/questions/143847

  •  02-07-2019
  •  | 
  •  

Frage

    

Diese Frage bereits eine Antwort hier:

         

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

Dies ist der beste Weg, ich weiß:

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
War es hilfreich?

Lösung

Wie von ECMAScript 2016 Sie verwenden können, includes()

arr.includes(obj);

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

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

EDIT: Dies wird nicht auf IE6 arbeiten, 7 oder 8 though. Die beste Abhilfe ist, es selbst zu definieren, wenn es 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);
      }
    );
    

Andere Tipps

Wenn Sie mit jQuery:

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

Für weitere Informationen: http://api.jquery.com/jQuery.inArray/

Als erstes implementieren indexOf in JavaScript für Browser, die es noch nicht haben. siehe zum Beispiel Erik Arvidsson Array Extras (auch die zugeordnet Blog-Post ). Und dann können Sie indexOf ohne sich Gedanken über die Browserunterstützung verwenden. 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 wird geändert, um die Länge zu speichern, so dass es nicht jede Iteration bis zu suchen braucht. Aber der Unterschied ist nicht sehr groß. Eine weniger Allzweck-Funktion könnte schneller sein:

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 ziehe die Standardfunktion verwenden und diese Art von Mikro-Optimierung Lassen, wenn es wirklich benötigt wird. Aber wenn Sie scharf auf Mikro-Optimierung ich die Benchmarks dass roosterononacid in den Kommentaren verknüpft, um in Arrays . Sie sind ziemlich obwohl roh, eine vollständige Untersuchung würde testen Arrays mit unterschiedlichen Typen, verschiedenen Längen und der Suche nach Objekten, die an verschiedenen Orten auftreten.

Wenn das Array unsortiert ist, gibt es nicht wirklich eine bessere Art und Weise (abgesehen von der Verwendung des oben erwähnte indexOf, die ich auf die gleiche Sache denke). Wenn das Array sortiert ist, können Sie eine binäre Suche, die wie folgt funktioniert:

  1. Wählen Sie das mittlere Element des Arrays.
  2. Ist das Element, das Sie sich für größer als das Element suchen Sie ausgewählt? Wenn ja, haben Sie die untere Hälfte des Feldes eliminiert. Wenn dies nicht der Fall, haben Sie die obere Hälfte eliminiert.
  3. Wählen Sie das mittlere Element der verbleibenden Hälfte des Feldes, und weiter wie in Schritt 2 Hälften des verbleibenden Array eliminiert wird. Schließlich werden Sie entweder Ihr Element finden oder haben kein Array durch aussehen links.

Binäre Suche läuft in der Zeit proportional zu dem Logarithmus der Länge des Arrays, so kann es sein, viel schneller als bei jedem einzelnen Elemente suchen.

[] .has (obj)

unter der Annahme .indexOf() 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
})

!!! nicht Array.prototype.has=function(){... machen, weil Sie in jedem Array ein enumerable Element hinzugefügt werden und js ist gebrochen.

//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 2. arg (Flag) Kräfte comparation von Wert statt Referenz

Vergleich rohe Objekte

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

Es hängt von Ihrem Ziel. Wenn Sie die Web-Programmierung vermeiden indexOf, ist es nicht von Internet Explorer 6 unterstützt wird, oder tun bedingte Nutzung (viele von ihnen noch verwendet!):

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

indexOf wird wahrscheinlich in nativen Code codiert, so ist es schneller als alles, was Sie in JavaScript (außer binärer Suche / Dichotomie, wenn das Array geeignet ist) tun. Hinweis: Es ist eine Frage des Geschmacks, aber ich würde eine return false; am Ende Ihrer Routine zu tun, zurückzukehren, um eine wahre Boolean ...

Hier ist ein Meta-Wissen für Sie - wenn Sie wissen wollen, was Sie mit einem Array tun können, überprüfen Sie die Dokumentation - hier ist der Array-Seite für Mozilla

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

Dort finden Sie Verweis auf indexOf sehen, aufgenommen in Javascript 1.6

Eine robuste Möglichkeit zu überprüfen, ob ein Objekt ein Array in Javascript ist detailliert hier:

Hier sind zwei Funktionen aus dem xa.js Rahmen, die ich zu einem utils = {} ‚Container‘ befestigen. Diese sollten helfen Sie richtig Arrays 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 ein Objekt in einem Array ist, würde ich auch diesen Code enthalten:

/**
 * 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 schließlich 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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top