Suchen Sie ein Objekt anhand der ID in einem Array von JavaScript-Objekten


1545

Ich habe ein Array:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

Ich kann die Struktur des Arrays nicht ändern. Mir wird eine ID von übergeben 45, und ich möchte 'bar'für dieses Objekt im Array abrufen.

Wie mache ich das in JavaScript oder mit jQuery?

Antworten:


1189

Verwenden Sie die find()Methode:

myArray.find(x => x.id === '45').foo;

Von MDN :

Die find()Methode gibt den ersten Wert im Array zurück, wenn ein Element im Array die bereitgestellte Testfunktion erfüllt. Andernfalls undefinedwird zurückgegeben.


Wenn Sie stattdessen den Index suchen möchten , verwenden Sie findIndex():

myArray.findIndex(x => x.id === '45');

Von MDN :

Die findIndex()Methode gibt den Index des ersten Elements im Array zurück, das die bereitgestellte Testfunktion erfüllt. Andernfalls wird -1 zurückgegeben.


Wenn Sie ein Array übereinstimmender Elemente erhalten möchten, verwenden Sie filter()stattdessen die folgende Methode:

myArray.filter(x => x.id === '45');

Dies gibt ein Array von Objekten zurück. Wenn Sie ein Array von fooEigenschaften erhalten möchten , können Sie dies mit der folgenden map()Methode tun :

myArray.filter(x => x.id === '45').map(x => x.foo);

Randnotiz: Methoden wie find()oder filter()und Pfeilfunktionen werden von älteren Browsern (wie IE) nicht unterstützt. Wenn Sie diese Browser unterstützen möchten, sollten Sie Ihren Code mit Babel (mit der Polyfüllung ) transpilieren .


2
Für mehrere Testbedingungen wäre es daher ungefähr so: myArray.find (x => x.id === '45' && x.color == 'red'). Foo
Apqu

2
Für mich die beste Antwort bisher. Benötigt weder jQuery noch das Erstellen neuer Auxiliar-Arrays.
Canta

myArray.find (x => x.id === '45') funktioniert nicht auf Mac-PC
Govinda Rajbhar

@TJCrowder Ich denke nicht, dass es eine gute Idee ist, Polyfills aus MDN in Ihren Code zu kopieren und einzufügen. Stattdessen sollten Sie npm-Pakete mit Polyfills verwenden. Und Babel enthält Polyfills für ES2015 + -Funktionen im Babel-Polyfill- Paket.
Michał Perłakowski

2
myArray.find (x => x.id === '45'). foo; löst eine Ausnahme aus, wenn kein Objekt mit der ID '45' vorhanden ist.
Frazer Kirkman

1466

Da Sie jQuery bereits verwenden, können Sie die grep- Funktion verwenden, die zum Durchsuchen eines Arrays vorgesehen ist:

var result = $.grep(myArray, function(e){ return e.id == id; });

Das Ergebnis ist ein Array mit den gefundenen Elementen. Wenn Sie wissen, dass das Objekt immer vorhanden ist und nur einmal vorkommt, können Sie es einfach verwenden result[0].foo, um den Wert abzurufen. Andernfalls sollten Sie die Länge des resultierenden Arrays überprüfen. Beispiel:

if (result.length === 0) {
  // no result found
} else if (result.length === 1) {
  // property found, access the foo property using result[0].foo
} else {
  // multiple items found
}

124
Es wäre sicherer, ===statt zu verwenden ==, um seltsame Probleme mit dem JavaScript- ==Operator zu vermeiden .
Vicky Chijwani

11
@ VickyChijwani: Gibt es Probleme beim Vergleich einer Zeichenfolge mit einer Zeichenfolge?
Guffa

38
Nun, wenn Sie absolut sicher , dass beide e.idund idwerden Strings sein, ich , es ist in Ordnung, Gebrauch annehmen ==. Aber wenn Sie sich nicht sicher sind, könnten Probleme auftreten (da '' == 0ist, trueaber '' === 0ist false). Ganz zu schweigen davon ===, dass es schneller zu sein scheint ( stackoverflow.com/questions/359494/… ).
Vicky Chijwani

101
Grundsätzlich benutze ich immer, ===weil es genau wie ==in anderen Programmiersprachen funktioniert . Ich halte ==es für nicht existent in JavaScript.
Vicky Chijwani

6
@de. Viele Antworten hier liefern das beabsichtigte Verhalten beim Nachschlagen eindeutiger Werte. Sie können sie im Wesentlichen daran erkennen, dass sie frühzeitig zurückkehren oder aus ihrer Schleife ausbrechen (oder ein Konstrukt niedrigerer Ebene anweisen, die Iteration zu beenden). Siehe JaredPars Antwort für ein kanonisches Beispiel und Aaronius 'Kommentar zu dieser Antwort für dieselbe Einsicht. Im Allgemeinen wird auf diese Weise zwischen "Filter" - und "Such" -Funktionen unterschieden, aber die Terminologie variiert. Obwohl dies effizienter ist, handelt es sich immer noch um eine lineare Suche. Wenn Sie also eine Hash-Tabelle verwenden möchten, lesen Sie die Antwort von Aaron Digulla (achten Sie auf implizite Details).
Der

362

Eine andere Lösung besteht darin, ein Suchobjekt zu erstellen:

var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
    lookup[array[i].id] = array[i];
}

... now you can use lookup[id]...

Dies ist besonders interessant, wenn Sie viele Suchvorgänge durchführen müssen.

Dies benötigt nicht viel mehr Speicher, da die IDs und Objekte gemeinsam genutzt werden.


6
Genau das, wonach ich gesucht habe. Komisch, wie ich versucht habe, es zu komplizieren, indem ich jedes Mal versucht habe, eine Schleife zu durchlaufen und jedes Element aus der Liste zu entfernen, wie ich es gefunden habe, als ich nur die von CouchDB empfangenen Daten mutieren und in ein für mich nützliches Format bringen musste Bedürfnisse. +1 Sir!
Slickplaid

5
das ist klug. Ich kann mir nicht vorstellen, wie andere davon überzeugt waren, bei jeder Verwendung das gesamte Array zu durchsuchen.
Aladdin Mhemed

4
Solange Sie sich nicht auf die Reihenfolge der Eigenschaften verlassen: stackoverflow.com/questions/4886314/…
Marle1

Verwendet eine Pause; in der Schleife eine gute Option / Verbesserung, wenn Sie wissen, dass es nur ein Objekt zu finden gibt?
irJvV

7
@irJvV: Nein, das macht überhaupt keinen Sinn. Der obige Code ist nützlich, wenn Sie viele Suchvorgänge durchführen müssen. Wenn Sie nur einmal hinschauen, ist das Erstellen eines lookupObjekts Zeitverschwendung.
Aaron Digulla

174

ECMAScript 2015 bietet die find () -Methode für Arrays:

var myArray = [
 {id:1, name:"bob"},
 {id:2, name:"dan"},
 {id:3, name:"barb"},
]

// grab the Array item which matchs the id "2"
var item = myArray.find(item => item.id === 2);

// print
console.log(item.name);

Es funktioniert ohne externe Bibliotheken. Wenn Sie jedoch Unterstützung für ältere Browser wünschen, können Sie diese Polyfüllung einschließen .


1
Wahrscheinlich, weil es immer noch sehr experimentell erscheint und nicht viele Browser es unterstützen, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
lejonl

2
Dies kann vereinfacht werden myArray.find(d=>d.id===45).foo;.
Shaggy

1
@ Shaggy oder sogar myArray.find(({ id }) => id === 45).foo. Dies ist jedoch eine alte Antwort, die geschrieben wurde, bevor die ES2015-Syntax genauso gut unterstützt wurde wie jetzt. @ Gothdos Antwort ist derzeit die aktuellste im Thread.
Rúnar Berg

1
@Shaggy Wenn .find () undefiniert zurückgibt, gibt Ihre Optimierung einen Fehler aus. Diese Lösung kann also nur in Fällen verwendet werden, in denen eine Übereinstimmung garantiert ist.
Herbert Peters

1
@HerbertPeters Wenn Sie sicher sein möchten, dass Sie immer eine Nullprüfung durchführen können, ist dies mit der optionalen Verkettung sehr einfach : myArray.find(d => d.id === 45)?.foo.
Rúnar Berg

141

Underscore.js hat dafür eine gute Methode:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })

42
Für die Aufzeichnung hat Lo-Dash (das oft nachweislich leistungsfähiger als Underscore ist) eine ähnliche Methode. Docs hier: lodash.com/docs#find
user456584

Wenn Sie nur ein Objekt erwarten, ist die Verwendung von findWhere effizienter, da die Suche nach dem Auffinden eines Ergebnisses nicht weiter geht.
foreever

@Foreever Aus den Dokumenten von _.find: "Die Funktion kehrt zurück, sobald sie ein akzeptables Element gefunden hat, und durchläuft nicht die gesamte Liste."
GijsjanB

129

Ich denke, der einfachste Weg wäre der folgende, aber er funktioniert nicht mit Internet Explorer 8 (oder früher):

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property

Ich bin gespannt, gibt es hier einen Leistungsvorteil gegenüber dem Üblichen for?
Igor Zinov'yev

@Igor Zinov'yev: Ja, diese ES5-Array-Tools haben sicherlich Auswirkungen auf die Leistung. Für jedes Element wird eine separate Funktion ausgeführt, sodass es im Vergleich zu einer direkten forSchleife nicht sehr schnell ist .
Pimvdb

Sie sagen also, dass es langsamer wäre? Außerdem wird, soweit ich sehen kann, immer das gesamte Array gescannt, während die forSchleife beim ersten Abgleich endet.
Igor Zinov'yev

Wenn Sie Unterstützung für IE8 benötigen, senden Sie
Adam Grant

Dieser Code wird einen Fehler id
Stan

71

Versuche Folgendes

function findById(source, id) {
  for (var i = 0; i < source.length; i++) {
    if (source[i].id === id) {
      return source[i];
    }
  }
  throw "Couldn't find object with id: " + id;
}

17
Dies war seiner eigenen Antwort nicht würdig, aber in modernen Browsern kann diese Lösung wie folgt
Rick

12
Wenn Sie Effizienz anstreben, beachten Sie, dass dieses Beispiel wahrscheinlich schneller ist als die Verwendung von filter () (siehe Ricks Beispiel), da dieses Beispiel zurückkehrt, sobald es das erste übereinstimmende Element gefunden hat, während filter () das gesamte Array auch nach dem Finden von a weiter durchläuft Spiel. Dieser hat auch nicht die Kosten für das Erstellen eines zusätzlichen Arrays oder das Aufrufen einer Funktion für jedes Element.
Aaronius

3
@ Rick, das Interessanteste an dieser Antwort ist anscheinend, dass Sie die Firebug-Konsole zum Ausgabefenster in jsFiddle hinzufügen können. Dies ist so viel besser, als sich zu protokollieren und jemand anderem zu sagen, dass er die Konsole öffnen soll, um die Ausgabe zu sehen. Genial!
KyleMit

1
Da es bisher noch niemand erwähnt hat, wollte ich hinzufügen, dass AngularJS auch eine Filtermethode hat .
Eno



31

Eine generische und flexiblere Version der obigen Funktion findById:

// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var result_obj = objectFindByKey(array, 'id', '45');

15

Sie können dies einfach mit der Funktion map () erreichen :

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var found = $.map(myArray, function(val) {
    return val.id == 45 ? val.foo : null;
});

//found[0] == "bar";

Arbeitsbeispiel: http://jsfiddle.net/hunter/Pxaua/


1
Ich habe vergessen, dass jQuery Elemente mapautomatisch entfernt null. Es klingt für mich und das gemeinsame Konzept von irreführend map, da das Ergebnis nicht die gleiche Länge wie die ursprüngliche Sammlung hat.
MaxArt

14

Sie können Filter verwenden,

  function getById(id, myArray) {
    return myArray.filter(function(obj) {
      if(obj.id == id) {
        return obj 
      }
    })[0]
  }

get_my_obj = getById(73, myArray);

1
@TobiasBeuving - Diejenige, die Array.find () verwendet, ist ebenfalls einfaches JS und sollte beim ersten Suchen angehalten werden, um effizienter zu sein.
Adrian Lynch

12

Obwohl es hier viele richtige Antworten gibt, sprechen viele von ihnen nicht die Tatsache an, dass dies eine unnötig teure Operation ist, wenn sie mehrmals ausgeführt wird. Im Extremfall kann dies die Ursache für echte Leistungsprobleme sein.

Wenn Sie in der realen Welt viele Elemente verarbeiten und die Leistung ein Problem darstellt, ist es viel schneller, zunächst eine Suche zu erstellen:

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

Sie können dann zu Gegenständen in fester Zeit wie folgt gelangen:

var bar = o[id];

Sie können auch eine Map anstelle eines Objekts als Lookup verwenden: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map


11

Native verwenden Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

Gibt das Objektelement zurück, wenn es gefunden wird false


Nur eine Anmerkung, Array.reduce wird in IE8 und darunter nicht unterstützt.
Burn_E99

7

Wenn Sie dies mehrmals tun, können Sie eine Karte (ES6) einrichten:

const map = new Map( myArray.map(el => [el.id, el]) );

Dann können Sie einfach tun:

map.get(27).foo

6

Hier ist, wie ich es in reinem JavaScript machen würde, so minimal ich mir vorstellen kann, dass dies in ECMAScript 3 oder höher funktioniert. Es wird zurückgegeben, sobald eine Übereinstimmung gefunden wurde.

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'

5

Allgemeiner und kurzer

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

in Ihrem Fall Ex. var element = findFromArray(myArray,'id',45)das wird dir das ganze Element geben.


4

Sie können Sugarjs unter http://sugarjs.com/ ausprobieren .

Es hat eine sehr süße Methode auf Arrays , .find. So können Sie ein Element wie dieses finden:

array.find( {id: 75} );

Sie können ihm auch ein Objekt mit mehr Eigenschaften übergeben, um eine weitere "where-Klausel" hinzuzufügen.

Beachten Sie, dass Sugarjs einheimische Objekte erweitert, und einige Leute halten dies für sehr böse ...


2
Nun, es ist böse, da es vorkommen kann, dass neue EcmaScript-Versionen neue Methoden mit demselben Namen einführen. Und raten Sie mal, genau das ist passiertfind . Mein Vorschlag ist, dass Sie, wenn Sie native Prototypen erweitern möchten, immer spezifischere Namen verwenden und die einfachsten zukünftigen Standardentwicklungen überlassen.
MaxArt

Dieser Kommentar ist fast 2 Jahre alt und heute würde ich sowieso lieber lodash verwenden. Wenn Sie möchten, können Sie dieses Thema jedoch auf der Website von sugarjs nachlesen. Sie nehmen einen guten Standpunkt zu Ihrer Meinung ein: Sugarjs.com/native
Deepflame

1
Die Operation bat speziell um eine Javascript- oder JQuery-Lösung
Tobias Beuving

4

Aufbauend auf der akzeptierten Antwort:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

Oder CoffeeScript:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo

4

In letzter Zeit muss ich mich dem gleichen Problem stellen, bei dem ich den String aus einem riesigen Array durchsuchen muss.

Nach einiger Suche fand ich, dass es mit einfachem Code einfach zu handhaben sein wird:

Code:

var items = mydata.filter(function(item){
    return item.word.toLowerCase().startsWith( 'gk );
})

Siehe https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/

Serach aus 20k Saiten


3

Iterieren Sie über ein Element im Array. Überprüfen Sie für jeden Artikel, den Sie besuchen, die ID dieses Artikels. Wenn es ein Match ist, geben Sie es zurück.

Wenn Sie nur den Codez wollen:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

Und dasselbe mit den Array-Methoden von ECMAScript 5:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}

3

Solange der Browser ECMA-262 , 5. Ausgabe (Dezember 2009) unterstützt, sollte dies funktionieren, fast einzeilig:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});

2
Fast. bFoundist nur ein Boolescher Wert, truewenn ein Element die erforderliche Bedingung erfüllt.
MaxArt

3

Sie können dies auch in reinem JavaScript tun, indem Sie die eingebaute "Filter" -Funktion für Arrays verwenden:

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}

Übergeben Sie nun einfach "id" anstelle von key"45" anstelle von "und" value, und Sie erhalten das vollständige Objekt, das einer ID von 45 entspricht.

myArr.filterObjects("id", "45");

16
Ändern Sie keine Objekte, die Sie nicht besitzen.
Michał Perłakowski

3

Verwenden Sie Array.prototype.filter()Funktion.

DEMO : https://jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON

var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];

FILTER

var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}

Wie kann ich innerhalb eines verschachtelten Objekts suchen? Wie Haustiere = falsch sollten zwei Objekte zurückgegeben werden.
Valay

Verwenden Sie die .filterMethode obj.infoin einer verschachtelten Schleife. var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
Sumit Ridhal

Sie könnten auch den es6-Stil verwenden ... const filterData = jsonObj.filter (obj => obj.name === 'Alex')
DagicCross

3

Wir können Jquery-Methoden verwenden $.each()/$.grep()

var data= [];
$.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}

oder

var data = $.grep(array, function( n, i ) {
  return ( n !== 5 && i > 4 );
});

Verwenden Sie die ES6-Syntax:

Array.find, Array.filter, Array.forEach, Array.map

Oder verwenden Sie Lodash https://lodash.com/docs/4.17.10#filter , Underscore https://underscorejs.org/#filter


2

Die Antwort von Aaron Digulla hat mir sehr gut gefallen, aber ich musste meine Reihe von Objekten behalten, damit ich sie später durchlaufen konnte. Also habe ich es geändert

	var indexer = {};
	for (var i = 0; i < array.length; i++) {
	    indexer[array[i].id] = parseInt(i);
	}
	
	//Then you can access object properties in your array using 
	array[indexer[id]].property


Verwendet dieselbe Lösung wie die schnellste, um Elemente im Array zu finden. Aber parseInt ist hier überflüssig.
Aleha

1

Verwenden:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

Es sollte ein Objekt mit der ID zurückgeben.


Sie könnten Ihren Code mit return obj.id verkürzen === 5? obj: falsch; Ich benutze $ .each viel, um über Arrays zu iterieren.
Marcel

@ Marcel: Das wird nicht funktionieren. Da die Rückgabe von false die Schleife beendet, wird das Objekt nur gefunden, wenn es das erste Element im Array ist.
Guffa

1

Diese Lösung kann auch hilfreich sein:

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

Ich habe es so gemacht, $.grepund wenn ein Objekt herausgefunden wird, gibt die Funktion das Objekt zurück und nicht ein Array.


2
Ändern Sie keine Objekte, die Sie nicht besitzen.
Michał Perłakowski

@ Gothdo Ich stimme zu. Wenn jemand nicht wusste, function will return the object, rather than an arraykann ein Fehler auftreten, aber ich denke, es hängt von den Benutzern ab.
Soytian

0

Ausgehend von der Antwort von aggaton ist dies eine Funktion, die tatsächlich das gewünschte Element zurückgibt (oder nullwenn sie nicht gefunden wird), vorausgesetzt , arrayund eine callbackFunktion, die einen wahrheitsgemäßen Wert für das "richtige" Element zurückgibt:

function findElement(array, callback) {
    var elem;
    return array.some(function(e) {
        if (callback(e)) {
            elem = e;
            return true;
        }
    }) ? elem : null;
});

Denken Sie daran, dass dies auf IE8- nativ nicht funktioniert, da es nicht unterstützt wird some. Eine Polyfüllung kann bereitgestellt werden, alternativ gibt es immer die klassische forSchleife:

function findElement(array, callback) {
    for (var i = 0; i < array.length; i++)
        if (callback(array[i])) return array[i];
    return null;
});

Es ist tatsächlich schneller und kompakter. Wenn Sie das Rad jedoch nicht neu erfinden möchten, empfehle ich die Verwendung einer Utility-Bibliothek wie Unterstrich oder Lodash.


0

Kürzeste,

var theAnswerObj = _.findWhere(array, {id : 42});

1
Dies erfordert die Verwendung der Unterstrichbibliothek. Das OP bat um eine einfache Javascript- oder jQuery-Lösung
Tobias Beuving

2
Sobald Sie einen Unterstrich einfügen, ist dies keine kurze Antwort!
Tim Ogilvy

-1

Betrachten Sie "axesOptions" als Array von Objekten mit einem Objektformat von {: field_type => 2 ,: fields => [1,3,4]}

function getFieldOptions(axesOptions,choice){
  var fields=[]
  axesOptions.each(function(item){
    if(item.field_type == choice)
        fields= hashToArray(item.fields)
  });
  return fields;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.