Was ist der richtige Weg, zwei Arrays in Javascript zusammenzuführen?
Ich habe zwei Arrays (zum Beispiel):
var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
Ich möchte in der Lage sein mit etwas zu enden:
var a3 = [{ id : 1, name : "test", count : "1"},
{ id : 2, name : "test2", count : "2"}]
Wo die beiden Arrays basierend auf dem 'id'-Feld verbunden werden, und zusätzliche Daten werden einfach hinzugefügt.
Ich habe versucht, _.union
dazu zu verwenden, aber es überschreibt einfach die Werte des zweiten Arrays in das erste
Das sollte den Trick tun:
var mergedList = _.map(a1, function(item){
return _.extend(item, _.findWhere(a2, { id: item.id }));
});
Dies setzt voraus, dass die ID des zweiten Objekts in a1 2 und nicht "2" sein sollte.
Angenommen, IDs sind Strings und die Reihenfolge spielt keine Rolle
Object.assign
(ES6 kann polyfilled sein).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];
});
Wenn die IDs in ECMAScript6 nicht unbedingt aus Zeichenfolgen bestehen, 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());
reduzieren Version.
var a3 = a1.concat(a2).reduce((acc, x) => {
acc[x.id] = Object.assign(acc[x.id] || {}, x);
return acc;
}, {});
_.values(a3);
Ich denke, dass es in der Funktionssprache üblich ist.
Die lodash-Implementierung:
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"
}
]
ES6 vereinfacht dies:
let merge = (obj1, obj2) => ({...obj1, ...obj2});
Beachten Sie, dass wiederholte Schlüssel zusammengeführt werden und der Wert des zweiten Objekts Vorrang hat und der wiederholte Wert des ersten Objekts ignoriert wird.
Beispiel:
let obj1 = {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj1Val"};
let obj2 = {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj2Val"};
merge(obj1, obj2)
// {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj2Val", uniqueObj2Key: "uniqueKeyValueObj2"}
merge(obj2, obj1)
// {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj1Val", uniqueObj1Key: "uniqueKeyValueObj1"}
Vanilla JS-Lösung
const a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
const a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
const merge = (arr1, arr2) => {
const temp = []
arr1.forEach(x => {
arr2.forEach(y => {
if (x.id === y.id) {
temp.Push({ ...x, ...y })
}
})
})
return temp
}
console.log(merge(a1, a2))
Es gibt bereits viele großartige Antworten, ich füge nur noch eine hinzu, die von einem echten Problem stammt, das ich gestern lösen musste.
Ich hatte ein Array von Nachrichten mit Benutzer-IDs und ein Array von Benutzern mit Benutzernamen und anderen Details. 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)
const a3 = a1.map(it1 => {
it1.test = a2.find(it2 => it2.id === it1.id).test
return it1
})
Dies sollte den Trick in es6 erfüllen und es ist funktional;
const a1 = [{ id: 1, name: 'test' }, { id: 2, name: 'test2' }];
const a2 = [{ id: 1, count: '1' }, { id: 2, count: '2' }];
const mergeArray = (source, merge, by) => source.map(item => ({
...item,
...(merge.find(i => i[by] === item[by]) || {}),
}));
console.log(mergeArray(a1, a2, 'id'));
// > [{ id: 1, name: 'test', count: '1' }, { id: 2, name: 'test2', count: '2' }]
Dies setzt auch voraus, dass die ID des zweiten Objekts in a1 2 und nicht "2" sein sollte.
Eine funktionierende TypeScript-Version:
export default class Merge {
static byKey(a1: any[], a2: any[], key: string) {
const res = a1.concat(a2).reduce((acc, x) => {
acc[x[key]] = Object.assign(acc[x[key]] || {}, x);
return acc;
}, {});
return Object.entries(res).map(pair => {
const [, value] = pair;
return value;
});
}
}
test("Merge", async () => {
const a1 = [{ id: "1", value: "1" }, { id: "2", value: "2" }];
const a2 = [{ id: "2", value: "3" }];
expect(Merge.byKey(a1, a2, "id")).toStrictEqual([
{
id: "1",
value: "1"
},
{ id: "2", value: "3" }
]);
});
Sie können so eine einfache Funktion zum Zusammenführen von Objekten schreiben
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;
}
Als Nächstes müssen Sie eine Doppelschleife verwenden, um sie auf Ihre Datenstruktur anzuwenden
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 können mergeObject
auch als einfachen Klon verwenden, indem Sie einen Parameter als leeres Objekt übergeben.