3
votes

Agréger deux tableaux d'objets

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


8 commentaires

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 pour a doit être 85, et c 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


7 Réponses :


0
votes

Voici comment j'ai abordé ce problème dans le passé.

  1. Créez un tableau final , qui contiendra le résultat final.
  2. Les tableaux sont fusionnés à l'aide de la méthode Array concat
  3. Le tableau concaténé est trié par la propriété name , ce qui signifie que tous les a seront dans l'ordre, puis les b, etc.
  4. La méthode 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);


0 commentaires

0
votes

Vous pouvez le faire avec l'aide de réduire .

  1. Commencez par fusionner les deux tableaux en utilisant concat .
  2. Maintenant sur le tableau concat en utilisant 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))


0 commentaires

0
votes

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);


0 commentaires

1
votes

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

  • un nouveau tableau avec des éléments de initial et àBeMerged ,
  • réduction des éléments de

    • recherche d'un élément avec le même nom dans l'accumulateur r ,
    • vérifier si l'élément n'est pas trouvé, puis renvoyer un nouveau tableau avec les itms collectés et une copie de l'objet réel
    • sinon, incrémentez les propriétés nécessaires avec certaines valeurs.

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);


1 commentaires

@Shidersz Aucune idée. Presque toutes les réponses ont été rejetées sans raison.



0
votes

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);


0 commentaires

2
votes

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)


0 commentaires

0
votes

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);


0 commentaires