webentwicklung-frage-antwort-db.com.de

JavaScript mischen Objekte nach ID

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

21
Tam2

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.

31
Gruff Bunny

Angenommen, IDs sind Strings und die Reihenfolge spielt keine Rolle 

  1. Erstellen Sie eine Hashtabelle.
  2. Iterieren Sie beide Arrays und speichern Sie die Daten in der Hash-Tabelle, indiziert nach der ID. Wenn bereits Daten mit dieser ID vorhanden sind, aktualisieren Sie sie mit Object.assign (ES6 kann polyfilled sein).
  3. Rufen Sie 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];
});

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());
12
Oriol

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.

6
Daishi Nakajima

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"
   }
]
4
bora89

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"}
4
Alberto

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))
2
Nick Olay

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)
2
Nick
const a3 = a1.map(it1 => {
   it1.test = a2.find(it2 => it2.id === it1.id).test
   return it1
 })
0
quy pham

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.

0
Micah

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" }
  ]);
});

0
Jeff Tian

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.

0
Paul S.