5
votes

Comment fusionner et remplacer des objets de deux tableaux en fonction d'une clé en javascript?

J'ai deux objets de tableau (arrayList1, arrayList2). J'essaie juste de fusionner ces deux tableaux en un seul objet tableau. J'ai utilisé les termes suivants.

  • Les deux tableaux fusionnés en un seul tableau basé sur le nom de la clé sont type .
  • Les valeurs
  • arrayList2 remplaceront la arrayList1.
  • J'ai obtenu le résultat attendu mais je me soucie de l'efficacité et de la performance.

Quelqu'un peut-il s'il vous plaît simplifier mon code ..

Remarque:

  • Ce serait génial si vous utilisez la fonction Array.reduce et sans utiliser de plugin / bibliothèque ..
  • J'ai ajouté la petite entrée pour comprendre. L'ordre des éléments sera modifié et la taille des deux tableaux changera.

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

result = arrayList2.reduce(function (arr1, arr2) {
  let isMatchFound = false;
  arr1.forEach(function (list) {
    if (arr2.type == list.type) {
      list = Object.assign(list, arr2);
      isMatchFound = true;
    }
  });
  if (!isMatchFound) {
    arr1.push(arr2);
  }
  return arr1;
}, arrayList1);

console.log('result', JSON.stringify(result));


6 commentaires

Que voulez-vous que la sortie soit? Quel devrait être le résultat ?


Quel est le cas d'utilisation ici. Quelle est la taille typique de la liste 1 et de la liste 2 ? Sont-ils toujours égaux? Je ne serai pas trop préoccupé par les performances tant que ce ne sera pas un problème. Lorsque la base de code est énorme, les goulots d'étranglement sont souvent ailleurs. La machine peut gérer les boucles etc. assez efficacement ces jours-ci.


@JackBashford - J'ai obtenu le résultat attendu. Je veux juste réduire le code de manière efficace et performante.


@SamuelToh, La taille de 'list-1' et 'list-2' sera modifiée .. La plupart du temps, le format de list1, list2 sera différent. J'ai juste ajouté quelques json pour comprendre ...


@RSKMR L'ordre des éléments est-il fixe, c'est-à-dire les premiers éléments de arrayList1 puis arrayList2?


@Ashish - non, l'ordre sera changé.


4 Réponses :


2
votes

Vous pouvez également utiliser les méthodes .reduce () et Object.values ​​() pour obtenir le résultat souhaité:

.as-console-wrapper { max-height: 100% !important; top: 0; }
const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

const result = Object.values(
   [].concat(arrayList1, arrayList2)
     .reduce((r, c) => (r[c.type] = Object.assign((r[c.type] || {}), c), r), {})
);
                 
console.log(result);


1 commentaires

Puisque Object.values ​​ ne garantie de venir dans un ordre particulier Je suggérerais plutôt d'utiliser une carte: [... [] .concat (arrayList1, arrayList2) .reduce ((r, c) => r.set (c .type, Object.assign (r.get (c.type) || {}, c)), r, new Map ()) .values ​​(),];



0
votes

Si vous vouliez simplement réduire la taille de votre code:

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

result = arrayList2.reduce(function(arr1, arr2) {
  if (arr1.find(({ type }) => type == arr2.type)) {
    arr1[arr1.indexOf(arr1.find(({ type }) => type == arr2.type))] = Object.assign(arr1.find(({ type }) => type == arr2.type), arr2);
    arr1.push(arr2);
  }
  return arr1;
}, arrayList1);

console.log('result', JSON.stringify(result));


1 commentaires

Le résultat attendu n'a pas été atteint. Veuillez vérifier ma sortie en question.



0
votes

Si vous n'avez pas exactement besoin de arrayList1 avant arrayList2, vous pouvez utiliser cette approche simple en une seule ligne. Ce que j'ai fait, c'est que j'ai déstructuré tous les éléments arrayList2 et uniquement les éléments de arrayList1 dont la clé n'existe pas dans arrayList1.

P.S. le problème avec réduire est que vous devez réduire le plus grand tableau sinon vous manquerez les éléments d'un plus grand tableau.

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];
const output = [...arrayList2, ...arrayList1.filter(el1 => !arrayList2.some(el2 => el2.type === el1.type))]
//[].concat(arrayList2, arrayList1.filter(el1 => !arrayList2.some(el2 => el2.type === el1.type)))

console.log(output)


0 commentaires

1
votes

Vous pouvez faire quelque chose comme ça en utilisant réduire et Object.values ​​

const array1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const array2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

const mapped = array1.reduce((a,t)=> (a[t.type] = t, a), {}),
      mapped2 = array2.reduce((a,t)=> (a[t.type] = t, a), {})

console.log(Object.values({...mapped, ...mapped2}))


1 commentaires

Voir le commentaire à la réponse de Mohammad Usman; l'ordre n'est pas garanti dans Object.values ​​donc si l'ordre est important et que vous voulez qu'il soit garanti, il est préférable d'utiliser Map.