Disons que j'ai ces deux tableaux:
const aggregated: Array<GivenObj> = [ {name: 'a', times: 85, other: 80}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 25, other: 22}, {name: 'd', times: 23, other: 10} ];
Ces deux tableaux contiennent des valeurs différentes, mais des clés similaires. J'ai besoin d'agréger ces données en un seul tableau qui contiendra leurs deux valeurs, mais de manière unique.
Dans le code, les deux tableaux ci-dessus doivent être agrégés comme suit:
const initial: Array<GivenObj> = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged: Array<GivenObj> = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ];
7 Réponses :
Voici comment j'ai abordé ce problème dans le passé.
final
, qui contiendra le résultat final. concat
name
, ce qui signifie que tous les a seront dans l'ordre, puis les b, etc. forEach
est utilisée pour parcourir le tableau concaténé et trié. Si l'élément courant a la même propriété name
que le dernier élément du tableau final
, ajoutez les propriétés numériques de el
au dernier élément du tableau final
. Sinon, ajoutez el
à la fin du tableau final.
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; let final = []; initial.concat(toBeMerged).sort((a, b) => a.name > b.name).forEach(el => { if (final.length > 0 && el.name === final[final.length - 1].name) { final[final.length - 1].times += el.times; final[final.length - 1].other += el.other; } else { final.push(el); } }) console.log(final);
Vous pouvez le faire avec l'aide de réduire .
concat
. réduire
nous vérifions si la propriété de l'objet est déjà présente dans la sortie
que nous ajoutons fois
et autre
dans la propriété existante sinon que nous ajoutons une nouvelle propriété.
const initial= [{name: 'a', times: 40, other: 50},{name: 'b', times: 10, other: 15},{name: 'c', times: 15, other: 12}]; const toBeMerged= [{name: 'a', times: 45, other: 30},{name: 'c', times: 10, other: 10},{name: 'd', times: 23, other: 10}]; let temp = initial.concat(toBeMerged) let op = temp.reduce((output,current)=>{ if( output[current.name] ){ output[current.name].times += current.times output[current.name].other += current.other } else{ output[current.name] = current; } return output; },{}) console.log(Object.values(op))
Essayez ce code
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; //console.log(initial); function arrayUnique(array) { var a = array.concat(); for(var i=0; i<a.length; ++i) { for(var j=i+1; j<a.length; ++j) { if(a[i].name === a[j].name) { a[i].times +=a[j].times; a[i].other +=a[j].other; a.splice(j--, 1); } } } return a; } // Merges both arrays and gets unique items var array = arrayUnique(initial.concat(toBeMerged)); console.log(array);
Vous pouvez réduire les données données et rechercher le même nom
, puis mettre à jour, sinon ajouter un nouvel objet.
Cela prend
initial
et àBeMerged
, réduction des éléments de
nom
dans l'accumulateur r
,
const initial = [{ name: 'a', times: 40, other: 50 }, { name: 'b', times: 10, other: 15 }, { name: 'c', times: 15, other: 12 }], toBeMerged = [{ name: 'a', times: 45, other: 30 }, { name: 'c', times: 10, other: 10 }, { name: 'd', times: 23, other: 10 }], merged = [...initial, ...toBeMerged].reduce((r, o) => { var temp = r.find(p => o.name === p.name); if (!temp) return [...r, { ...o }]; temp.times += o.times; temp.other += o.other; return r; }, []); console.log(merged);
@Shidersz Aucune idée. Presque toutes les réponses ont été rejetées sans raison.
Ici, vous avez une approche utilisant réduire () et findIndex () sur le nouveau tableau à fusionner. Si un nouvel objet à fusionner existe déjà (c'est-à-dire que la propriété name
correspond à un objet), nous incrémentons le reste des propriétés correspondantes et ajoutons celles qui n'existent pas, sinon nous poussons le nouvel objet entier :
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30, another: 76}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; let newArray = toBeMerged.reduce((res, curr) => { let found = res.findIndex(x => x.name === curr.name); if (found >= 0) { res[found] = Object.keys(curr).reduce((r, c) => { r[[c]] = (r[[c]] && c !== 'name') ? r[[c]] + curr[[c]] : curr[[c]]; return r; }, res[found]); } else { res.push(curr); } return res; }, initial); console.log(newArray);
J'aborderais cela en fusionnant les deux tableaux, puis en exécutant une réduction sur ce tableau combiné.
À l'intérieur de la réduction, il vérifie d'abord si une entrée avec ce nom existe, sinon il pousse cette entrée vers le tableau de résultats. S'il trouve une entrée existante, il crée toute propriété qui n'existe pas et ajoute les valeurs de toutes les propriétés numériques qui existent déjà. Cela devrait être suffisamment flexible pour quel que soit votre cas d'utilisation réel.
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; const result = [ ...initial, ...toBeMerged ].reduce((arr, t) => { let existing = arr.filter(x => x.name == t.name)[0] if(!existing) arr.push(t) else { const keys = Object.keys(t) keys.forEach(key => { if(!existing.hasOwnProperty(key)) existing[key] = t[key] else if(typeof existing[key] === "number") existing[key] += t[key] }) } return arr }, []) console.log(result)
Utilisation de l'opérateur de propagation, de la déstructuration, du tableau # réduire, des valeurs de l'objet # et de la carte
const initial=[{name:'a',times:40,other:50},{name:'b',times:10,other:15},{name:'c',times:15,other:12}];const toBeMerged=[{name:'a',times:45,other:30},{name:'c',times:10,other:10},{name:'d',times:23,other:10}] const res = [...[...initial, ...toBeMerged] .reduce((a,{name,times,other})=>{ const b = a.get(name); return a.set(name,{name, times: (b?b.times:0) + times, other: (b?b.other:0) + other}); }, new Map()).values()]; console.log(res);
Vous devrez effectuer une boucle, trouver des doublons et faire le calcul. Il n'y a pas de méthode prête à l'emploi pour combiner réellement les valeurs de propriété. As-tu essayé?
@isherwood En effet, j'ai essayé. Mais c'était comme si la solution de quelqu'un d'autre pouvait être plus efficace que la mienne.
postez votre code alors s'il vous plaît
Le résultat pour
fois
poura
doit être 85, etc
est faux pour les deux valeurs.qui vote presque toutes les réponses?
C'est un vidage de code. Personne à part jmcgriz n'a pris la peine d'expliquer ce que fait leur code.
@Andy merci, les valeurs sont fixes.
@EliyaCohen Il y a de fortes chances que le vote négatif soit dû au fait que vous n'avez fourni aucun code. Vous devez montrer ce que vous avez essayé, même si cela ne fonctionne pas, lorsque vous le demandez. De cette façon, les répondeurs peuvent évaluer votre niveau de compétence et vous conseiller de manière appropriée