2013-10-20 10 views
15

Was ist der richtige Weg, um zwei Arrays in Javascript zusammenzuführen?JavaScript Objekte durch ID zusammenführen

Ich habe zwei Arrays (zum Beispiel) bekam:

var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}] 
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}] 

ich mit etwas, um am Ende in der Lage sein wollen, wie:

var a3 = [{ id : 1, name : "test", count : "1"}, 
      { id : 2, name : "test2", count : "2"}] 

Wo die beiden Arrays verbunden sind, basiert auf Das Feld "ID" und zusätzliche Daten werden einfach hinzugefügt.

Ich versuchte _.union zu verwenden, um dies zu tun, aber es überschreibt einfach die Werte aus der zweiten Reihe in die erste

+1

Also was Sie eigentlich tun möchten, ist die Objekte zusammenführen. – JJJ

+0

Ihre Syntax ist ungültig. Hast du ein echtes Beispiel? –

+0

möglich duplizieren von http://stackoverflow.com/questions/1584370/how-to-merge-two-arrays-in-javascript –

Antwort

29

Diese den Trick tun sollten:

var mergedList = _.map(a1, function(item){ 
    return _.extend(item, _.findWhere(a2, { id: item.id })); 
}); 

sollte 2 statt „2“

+0

Perfekt , danke – Tam2

+1

Dies funktioniert nicht, wenn a2 mehr Elemente im Array als a1 hat. – CAOakley

+1

@ CAOakley - ja, es wird. Was lässt dich denken, dass es nicht funktioniert? –

0

Sie ein einfaches Objekt verschmelzen Funktion wie dieses

function mergeObject(cake, icing) { 
    var icedCake = {}, ingredient; 
    for (ingredient in cake) 
     icedCake[ingredient] = cake[ingredient]; 
    for (ingredient in icing) 
     icedCake[ingredient] = icing[ingredient]; 
    return icedCake; 
} 

Weiter schreiben kann, Sie tun müssen, um einen Doppel-Loop verwenden, um Ihre Daten structre

var i, j, a3 = a1.slice(); 
for (i = 0; i < a2.length; ++i)    // for each item in a2 
    for (j = 0; i < a3.length; ++i)   // look at items in other array 
     if (a2[i]['id'] === a3[j]['id'])  // if matching id 
      a3[j] = mergeObject(a3[j], a2[i]); // merge 

Sie auch mergeObject als einfacher Klon verwenden, um anwenden können, , indem ein Parameter als leeres Objekt übergeben wird.

11

Angenommen IDs Strings sind und die Reihenfolge egal Dies setzt voraus, dass die ID des zweiten Objekts in a1 nicht Sie können

  1. Erstellen Sie eine Hashtabelle.
  2. Iterieren Sie beide Arrays und speichern Sie die Daten in der Hash-Tabelle, indiziert durch die ID. Wenn bereits Daten mit dieser ID vorhanden sind, aktualisieren Sie sie mit Object.assign (ES6, kann polyfilled sein).
  3. Ruft ein Array mit den Werten der Hash-Map ab.
var hash = Object.create(null); 
a1.concat(a2).forEach(function(obj) { 
    hash[obj.id] = Object.assign(hash[obj.id] || {}, obj); 
}); 
var a3 = Object.keys(hash).map(function(key) { 
    return hash[key]; 
}); 

In ECMAScript6, wenn die IDs nicht notwendigerweise Strings sind, können Sie Map verwenden:

var hash = new Map(); 
a1.concat(a2).forEach(function(obj) { 
    hash.set(obj.id, Object.assign(hash.get(obj.id) || {}, obj)) 
}); 
var a3 = Array.from(hash.values()); 
3

reduce Version.

var a3 = a1.concat(a2).reduce((acc, x) => { 
    acc[x.id] = Object.assign(acc[x.id] || {}, x); 
    return acc; 
}, {}); 
_.values(a3); 

Ich denke, es ist in der funktionalen Sprache üblich.

4

Die lodash implementaiton:

var merged = _.map(a1, function(item) { 
    return _.assign(item, _.find(a2, ['id', item.id])); 
}); 

Das Ergebnis:

[ 
    { 
     "id":1, 
     "name":"test", 
     "count":"1" 
    }, 
    { 
     "id":2, 
     "name":"test2", 
     "count":"2" 
    } 
] 
1

Schon jetzt gibt es viele tolle Antworten, ich werde nur noch eine hinzufügen, die von einem echten Problem ist, das ich gestern zu lösen benötigt .

Ich hatte ein Array von Nachrichten mit Benutzer-IDs, und ein Array von Benutzern, die Benutzernamen und andere Details enthalten. So habe ich es geschafft, den Nachrichten Benutzerdetails hinzuzufügen.

var messages = [{userId: 2, content: "Salam"}, {userId: 5, content: "Hello"},{userId: 4, content: "Moi"}]; 
var users = [{id: 2, name: "Grace"}, {id: 4, name: "Janetta"},{id: 5, name: "Sara"}]; 

var messagesWithUserNames = messages.map((msg)=> { 
    var haveEqualId = (user) => user.id === msg.userId 
    var userWithEqualId= users.find(haveEqualId) 
    return Object.assign({}, msg, userWithEqualId) 
}) 
console.log(messagesWithUserNames) 
Verwandte Themen