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 steht in engem Zusammenhang mit der Stack Overflow-Frage Beste Methode, um ein Element in einem JavaScript-Array zu finden?, Das die Suche nach Objekten in einem Array mithilfe von indexOf
anspricht.
Aktuelle Browser haben Array#includes
, was genau that, wird weitgehend unterstützt und für ältere Browser ein polyfill hat.
> ['joe', 'jane', 'mary'].includes('jane');
true
Sie können auch Array#indexOf
verwenden. Dies ist weniger direkt, erfordert jedoch keine Polyfills für veraltete Browser.
jQuery bietet $.inArray
an, was funktional Array#indexOf
entspricht.
underscore.js , eine JavaScript-Hilfsprogrammbibliothek, bietet _.contains(list, value)
, Alias _.include(list, value)
, die beide intern indexOf verwenden, wenn ein JavaScript-Array übergeben wird.
Einige andere Frameworks bieten ähnliche Methoden an:
dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(ist _.contains
älter als 4.0.0)array.includes(value)
Beachten Sie, dass einige Frameworks dies als Funktion implementieren, während andere sie dem Array-Prototyp hinzufügen.
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 selbst.
Wie andere bereits gesagt haben, ist die Iteration durch das Array wahrscheinlich der beste Weg, aber wurde bewiesen , dass eine abnehmende while
-Schleife der schnellste Weg ist, um in JavaScript zu iterieren. Sie können Ihren Code also 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
indexOf
NAME _ 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, aber Sie können Arrays in Internet Explorer (und eine ähnliche Funktionalität hinzufügen andere Browser, die indexOf
nicht unterstützen), wenn Sie möchten, wie eine schnelle Google-Suche zeigt (zum Beispiel diese ).
ECMAScript 7 führt Array.prototype.includes
ein.
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, vergleicht includes
den SameValueZero - Gleichheitsalgorithmus. Das bedeutet, dass Sie feststellen können, ob ein Array eine NaN
enthält:
[1, 2, NaN].includes(NaN); // true
Anders als indexOf
überspringt includes
fehlende Indizes nicht:
new Array(5).includes(undefined); // true
Derzeit ist es noch ein Entwurf, es kann jedoch polyfilled sein, damit es in allen Browsern funktioniert.
b
ist der Wert und a
ist das Array. Es gibt true
oder false
zurück:
function(a, b) {
return a.indexOf(b) != -1
}
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;
};
}
Die obersten Antworten gehen von primitiven Typen aus. Wenn Sie jedoch herausfinden möchten, ob ein Array ein Objekt mit bestimmten Eigenschaften enthält, ist Array.prototype.some () eine sehr elegante Lösung:
const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
items.some(item => item.a === '3') // returns true
items.some(item => item.a === '4') // returns false
Das Schöne daran ist, dass die Iteration abgebrochen wird, sobald das Element gefunden wurde, sodass unnötige Iterationszyklen eingespart werden.
Außerdem passt es gut in eine if
-Anweisung, da es einen Booleschen Wert zurückgibt:
if (items.some(item => item.a === '3')) {
// do something
}
* Wie jamess in dem Kommentar darauf hinweist, wird Array.prototype.some()
ab heute, September 2018, vollständig unterstützt: caniuse.com Support-Tabelle
Benutzen:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
Das Erweitern des JavaScript-Objekts Array
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 - Bibliothek 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.
Wenn Sie für eine Sekunde aus dem Kasten heraus denken, wenn Sie diesen Anruf viele Male tätigen, ist die Verwendung wesentlich effizienter ein assoziatives Array eine Map, um Lookups mit einer Hash-Funktion durchzuführen.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Einzeiler:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
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
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
Eine hoffentlich schnellere bidirektionale indexOf
/lastIndexOf
alternative
Während die neue Methode include sehr nett ist, ist der Support im Moment null.
Ich habe lange daran gedacht, die langsamen Funktionen indexOf/lastIndexOf zu ersetzen.
Es wurde bereits ein performanter Weg gefunden, der die wichtigsten Antworten betrachtet. Von diesen habe ich die contains
-Funktion ausgewählt, die von @Damir Zekic gepostet wurde, die die schnellste sein sollte. Es heißt aber auch, dass die Benchmarks aus dem Jahr 2008 stammen und somit veraltet sind.
Ich bevorzuge auch while
gegenüber for
, aber aus einem bestimmten Grund beendete ich das Schreiben der Funktion mit einer for-Schleife. Es könnte auch mit einem while --
durchgeführt werden.
Ich war gespannt, ob die Iteration viel langsamer war, wenn ich währenddessen beide Seiten des Arrays überprüfe. Anscheinend nein, und daher ist diese Funktion etwa zweimal schneller als die Top-Stimmen. Natürlich ist es auch schneller als der native. In einer realen Umgebung, in der Sie nie wissen, ob der von Ihnen gesuchte Wert am Anfang oder am Ende des Arrays liegt.
Wenn Sie wissen, dass Sie gerade ein Array mit einem Wert gepusht haben, ist die Verwendung von lastIndexOf wahrscheinlich die beste Lösung. Wenn Sie jedoch große Arrays durchlaufen müssen und das Ergebnis überall vorhanden sein könnte, könnte dies eine solide Lösung sein, um die Abläufe zu beschleunigen.
Bidirektionaler 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');
http://jsperf.com/bidirectionalindexof
Als Test habe ich ein Array mit 100k Einträgen erstellt.
Drei Abfragen: am Anfang, in der Mitte und am Ende des Arrays.
Ich hoffe, Sie finden das auch interessant und testen die Leistung.
Hinweis: Wie Sie sehen, habe ich die Funktion contains
etwas geändert, um die Ausgabe von indexOf & lastIndexOf wiederzugeben (also im Grunde true
mit index
und false
mit -1
). Das sollte nicht schaden.
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 wahr oder falsch oder sogar das Objekt, den String oder was auch immer es ist, zurückzugeben.
Und hier ist die Variable while
:
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');
Ich denke, dass die einfache Berechnung, um den reflektierten Index in einem Array zu erhalten, so einfach ist, dass sie zweimal schneller ist als eine tatsächliche Schleifeniteration.
Hier ist ein komplexes Beispiel, das drei Prüfungen pro Iteration durchführt. Dies ist jedoch nur bei einer längeren Berechnung möglich, die zu einer Verlangsamung des Codes führt.
Wenn Sie wiederholt prüfen, ob ein Objekt in einem Array vorhanden ist, sollten Sie dies vielleicht überprüfen
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
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 er gefunden wird, oder -1, falls nicht gefunden
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 ursprünglichen Code erhalten.
Verwenden Sie lodash's einige Funktion.
Es ist prägnant, präzise und bietet eine hervorragende Plattformunterstützung.
Die akzeptierte Antwort erfüllt nicht einmal die Anforderungen.
Anforderungen: Empfiehlt eine präzise und effiziente Methode, um herauszufinden, ob ein JavaScript-Array ein Objekt enthält.
Akzeptierte Antwort:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
Meine Empfehlung:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Anmerkungen:
$ .inArray funktioniert gut, um zu bestimmen, ob ein scalar -Wert in einem Array von Skalaren vorhanden ist ...
$.inArray(2, [1,2])
> 1
... aber die Frage verlangt eindeutig nach einer effizienten Methode, um festzustellen, ob ein object in einem Array enthalten ist.
Um sowohl Skalare als auch Objekte zu behandeln, können Sie Folgendes tun:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
Lösung, die in allen modernen Browsern funktioniert:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Verwendungszweck:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6 + Lösung:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Verwendungszweck:
contains([{a: 1}, {a: 2}], {a: 1}); // true
JSON.stringify
verwenden?Array.indexOf
und Array.includes
(sowie die meisten Antworten hier) werden nur nach Verweis und nicht nach Wert verglichen.
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
Nicht optimierter ES6-Einliner:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
Hinweis: Das Vergleichen von Objekten nach Wert funktioniert besser, wenn sich die Schlüssel in derselben Reihenfolge befinden. Um sicher zu sein, können Sie die Schlüssel zuerst mit einem Paket wie diesem sortieren: https://www.npmjs.com/ Paket/Sortierschlüssel
contains
-Funktion wurde mit einer Perf-Optimierung aktualisiert. Danke itinance für den Hinweis.
array.indexOf(x)!=-1
ist zwar die präziseste Methode (und wird seit über zehn Jahren von Nicht-Internet Explorer-Browsern unterstützt ...), aber 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 table[x]!==undefined
oder ===undefined
aus:
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.) JavaScript verfügt nicht über ausreichende Hooks Lassen Sie diesen Status im Gegensatz zu Python zum Beispiel bei.)
ECMAScript 6 hat einen eleganten Vorschlag zum Finden.
Die find-Methode führt die Callback-Funktion einmal für jedes Element aus im Array vorhanden, bis ein Array gefunden wird, in dem Callback ein wahres _ zurückgibt. Wert. Wenn ein solches Element gefunden wird, gibt find sofort den Wert .__ zurück. dieses Elements. Andernfalls suchen Sie die Rückgaben undefiniert. Rückruf ist wird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen wurden; es wird nicht für Indizes aufgerufen, die gelöscht wurden oder die niemals wurden Werte zugewiesen.
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 darunter 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;
}
});
}
Benutzen:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
Um genau zu wissen, was die tilde
~
an dieser Stelle tut, lesen Sie diese Frage Was macht eine Tilde, wenn sie vor einem Ausdruck steht?.
So macht Prototype es :
/**
* Array#indexOf(item[, offset = 0]) -> Number
* - item (?): A value that may or may not be in the array.
* - offset (Number): The number of initial items to skip before beginning the
* search.
*
* Returns the position of the first occurrence of `item` within the array — or
* `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
Siehe auch hier wie sie es anschließen.
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
}
OK, du kannst einfach optimiere deinen Code um das Ergebnis zu erhalten!
Es gibt viele Möglichkeiten, dies zu tun, die sauberer und besser sind, aber ich wollte nur Ihr Muster bekommen und es mit JSON.stringify
anwenden.
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
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 des Array-Objekts ist möglicherweise nicht sinnvoll, aber manchmal ist es in Ordnung (wenn Sie sich dessen und dem Kompromiss bewusst sind).
Man kann Set verwenden, 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'));
Array.indexOf(Object)
. Array.includes(Object)
verwendet werden. Mit ECMA 6 können Sie Array.find(FunctionName)
verwenden, wobei FunctionName
eine vom Benutzer definierte Funktion ist.
Hoffe das hilft!
Wie bereits erwähnt, können Sie Array.indexOf
verwenden, es ist jedoch nicht in allen Browsern verfügbar. Hier ist der Code aus 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 solche kann es nicht in allen Browsern vorhanden sein. Sie können dies umgehen, indem Sie .__ einfügen. Der folgende Code am Anfang Ihrer Skripte erlaubt die Verwendung von indexOf in Implementierungen, die es nicht nativ unterstützen. Diese Der Algorithmus ist genau der in ECMA-262, 5. Auflage, .__ angegebene. Angenommen, 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;
}
}
Überrascht, dass zu dieser Frage immer noch keine neue Syntax hinzugefügt wurde, die meine 2 Cent hinzufügt.
Nehmen wir an, wir haben ein Array von Objekten arrObj und möchten obj darin suchen.
Array.prototype.indexOf -> (gibt index oder -1 zurück) wird im Allgemeinen verwendet, um den Index eines Elements im Array zu finden. Dies kann auch zum Suchen von Objekten verwendet werden, funktioniert jedoch nur, wenn Sie einen Verweis auf dasselbe Objekt übergeben.
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
Array.prototype. includes -> (gibt true oder false zurück)
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
Array.prototype. find -> (nimmt einen Rückruf entgegen, gibt zuerst value/object zurück, das in CB true zurückgibt).
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
Array.prototype. findIndex -> (nimmt einen Rückruf entgegen, gibt index des ersten Werts/Objekts zurück, der in CB true zurückgibt).
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
Da find und findIndex einen Rückruf annehmen, können wir jedes Objekt (auch wenn wir nicht über die Referenz verfügen) aus dem Array abrufen, indem wir die wahre Bedingung kreativ festlegen.
Auf keinen Fall das Beste, aber ich wurde gerade kreativ und fügte das Repertoire hinzu.
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'));
Ich habe die eingereichten Antworten durchgesehen und erfuhr, dass sie nur zutreffen, wenn Sie das Objekt per Referenz suchen. Eine einfache lineare Suche mit Referenzobjektvergleich.
Aber nehmen wir an, Sie haben keinen Verweis auf ein Objekt. Wie finden Sie das richtige Objekt im Array? Sie müssen mit jedem Objekt einen linearen und tiefen Vergleich durchführen. Stellen Sie sich vor, wenn die Liste zu groß ist und die darin enthaltenen Objekte sehr groß sind und große Textteile enthalten. Die Leistung sinkt drastisch mit der Anzahl und Größe der Elemente im Array.
Sie können Objekte stringifizieren und in die systemeigene Hashtabelle einfügen, dann haben Sie jedoch Datenredundanz, die diese Schlüssel in Erinnerung bringt, da JavaScript sie für 'for i in obj' hält, und Sie möchten nur prüfen, ob das Objekt vorhanden ist oder nicht Du hast den Schlüssel.
Ich habe darüber nachgedacht, einen JSON-Schema-Validator zu erstellen, und habe einen einfachen Wrapper für die native Hash-Tabelle entwickelt, der der einzigen Hash-Implementierung ähnlich ist, mit einigen Optimierungsausnahmen, die ich der native Hash-Tabelle überlassen musste. Es ist nur ein Leistungs-Benchmarking erforderlich ....__ Alle Details und Code finden Sie in meinem Blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a -large-array/ Ich werde in Kürze Benchmark-Ergebnisse veröffentlichen.
Die Komplettlösung funktioniert so:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
Wenn Sie mit ES6 arbeiten, können Sie ein Set verwenden:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
Dies sollte performanter sein als bei jeder anderen Methode
Oder diese Lösung:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
Ähnliches: Findet das erste Element durch ein "Suchlambda":
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
Verwendungszweck:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
Gleiches in Kaffeescript:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
Ich habe an einem Projekt gearbeitet, bei dem ich eine Funktionalität wie Python set
benötigte, die alle Duplikate entfernt und eine neue Liste zurückgibt. Ich habe diese Funktion also für jemanden nützlich geschrieben
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.Push(arr[i]);
}
}
return res;
}
Ich empfahl, die Unterstreichungsbibliothek zu verwenden, da sie den Wert zurückgibt und für alle Browser unterstützt wird.
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
Es hat einen Parameter: eine Array-Anzahl von Objekten. Jedes Objekt im Array verfügt über zwei ganzzahlige Eigenschaften, die mit x und y bezeichnet werden. Die Funktion muss eine Anzahl aller Objekte im Array zurückgeben, die numbers.x == numbers.y
entsprechen.
var numbers = [ { x: 1, y: 1 },
{ x: 2, y: 3 },
{ x: 3, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 } ];
count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
Mit idnexOf () ist es eine gute Lösung, aber Sie sollten die eingebettete Implementierungsfunktion indexOf () ausblenden, die -1 mit dem Operator ~ zurückgibt:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
Zusätzlich zu dem, was andere sagten, wenn Sie keinen Verweis auf das Objekt haben, das Sie im Array suchen möchten, können Sie so etwas tun.
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
Array.some gibt true zurück, wenn ein Element der angegebenen Bedingung entspricht, und gibt false zurück, wenn keines der Elemente der angegebenen Bedingung entspricht.
Verwenden Sie JavaScript-In-Build-Funktion
var optval = [];
optval.Push('A');
optval.Push('B');
optval.Push('C');
Wir können den String A im Javascript-Array wie folgt durchsuchen:
optval.includes('A') // =====> return true
Einfache Lösung: ES6 Features " include " Methode
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
function countArray(originalArray) {
var compressed = [];
// make a copy of the input array
var copyArray = originalArray.slice(0);
// first loop goes over every element
for (var i = 0; i < originalArray.length; i++) {
var count = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copyArray.length; w++) {
if (originalArray[i] == copyArray[w]) {
// increase amount of times duplicate is found
count++;
// sets item to undefined
delete copyArray[w];
}
}
if (count > 0) {
var a = new Object();
a.value = originalArray[i];
a.count = count;
compressed.Push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);