3
votes

Comment fusionner / concaténer les valeurs des mêmes propriétés d'objet dans un tableau d'objets à l'aide de lodash?

J'ai un tableau de tableaux d'objets qui ressemble à ceci:

test = [
  {'id': 1,'type': 'apples','samples': [11, 2, 33]},
  {'id': 2,'type': 'bananas','samples': [17, 2, 67]},
  {'id': 3,'type': 'pears','samples': [91, 22, 34]}
]

Je veux réduire et fusionner le tableau ci-dessus en utilisant lodash en un seul afin que les échantillons soient concaténés comme ceci:

let test = _(fruitSamples)
  .flatten()
  .groupBy('type')
  .map(_.spread(_.merge))
  .value();

console.log(test);

J'ai essayé de nombreuses approches différentes, mais comme je veux le moyen le plus court possible de résoudre ce problème, quelles seraient vos recommandations?

J'ai essayé ceci:

fruitSamples = [
  {'id': 1, 'type': 'apples', 'samples': [1,2,3,5,2,9,11,2,33]},
  {'id': 2, 'type': 'bananas', 'samples': [1,2,7,1,7,7,17,2,67]},
  {'id': 3, 'type': 'pears', 'samples': [1,2,3,12,21,32,91,22,34]},
]

Cela me donne le résultat suivant, qui ne concatène pas les échantillons:

let fruitSamples = [
  [
    {'id': 1,'type': 'apples','samples': [1, 2, 3]},
    {'id': 2,'type': 'bananas','samples': [1, 2, 7]},
    {'id': 3,'type': 'pears','samples': [1, 2, 3]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [5, 2, 9]},
    {'id': 2,'type': 'bananas','samples': [1, 7, 7]},
    {'id': 3,'type': 'pears','samples': [12, 21, 32]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [11, 2, 33]},
    {'id': 2,'type': 'bananas','samples': [17, 2, 67]},
    {'id': 3,'type': 'pears','samples': [91, 22, 34]}
  ]
];


0 commentaires

4 Réponses :


1
votes

Je ne sais pas comment utiliser lodash, mais du pur Javascript, ce n'est pas trop difficile.

Mise à jour: Merci à @Taki de faire un flat () d'abord rend cela même plus facile ..

let fruitSamples = [[{"id":1,"type":"apples","samples":[1,2,3]},{"id":2,"type":"bananas","samples":[1,2,7]},{"id":3,"type":"pears","samples":[1,2,3]}],[{"id":1,"type":"apples","samples":[5,2,9]},{"id":2,"type":"bananas","samples":[1,7,7]},{"id":3,"type":"pears","samples":[12,21,32]}],[{"id":1,"type":"apples","samples":[11,2,33]},{"id":2,"type":"bananas","samples":[17,2,67]},{"id":3,"type":"pears","samples":[91,22,34]}]];

let concat = fruitSamples.flat().reduce((a, i) => {
  const f = a.find(f => f.id === i.id);
  if (!f) a.push(i);
  else f.samples = [...f.samples, ...i.samples];
  return a;
}, []);

console.log(concat);


3 commentaires

vous pouvez éviter les boucles imbriquées si vous utilisez fruitSamples.flat (). reduction ()


Fonctionne comme un charme, même si je pense que la méthode flat () ne fonctionne pas dans les anciennes versions de chrome et de certains autres navigateurs (je ne les ai pas tous testés), je vais donc m'en tenir à l'utilisation de forEach pour le moment. À votre santé.


@Daybreak Pas de problème ,. Toutes les réponses que je donne, j'essaie toujours d'utiliser des techniques Javascript modernes, j'aime aller de l'avant et non en arrière. Avec polyfill's & transpilers, le moyen standard de créer une bonne application Web, il n'y a aucune raison de ne pas trop :)



0
votes

Vous pouvez d'abord convertir le ou les tableaux en tableau simple en utilisant .reduce , puis le grouper en utilisant .reduce à nouveau.

Peut-être plus facile à saisir

Quelque chose comme

let fruitSamples = [
  [
    {'id': 1,'type': 'apples','samples': [1, 2, 3]},
    {'id': 2,'type': 'bananas','samples': [1, 2, 7]},
    {'id': 3,'type': 'pears','samples': [1, 2, 3]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [5, 2, 9]},
    {'id': 2,'type': 'bananas','samples': [1, 7, 7]},
    {'id': 3,'type': 'pears','samples': [12, 21, 32]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [11, 2, 33]},
    {'id': 2,'type': 'bananas','samples': [17, 2, 67]},
    {'id': 3,'type': 'pears','samples': [91, 22, 34]}
  ]
];

var merged = fruitSamples.reduce(function(prev, next) {
  return prev.concat(next);
});

var res = merged.reduce(function(prev, next) {
      
      var index = prev.findIndex(o=> o.id == next.id) 
         if(index >= 0)
           prev[index].samples = [...prev[index].samples,...next.samples];
           else
           prev.push(next);
           
           return prev;
},[]);

console.log(res)


0 commentaires

2
votes

Au lieu de _.merge , vous pouvez essayer d'utiliser _. mergeWith qui accepte une fonction de customizer que vous pouvez utiliser pour personnaliser les valeurs assignées.

À partir de documents officiels :

Cette méthode est comme _.merge sauf qu'elle accepte le personnalisateur qui est invoqué pour produire les valeurs fusionnées de la destination et de la source Propriétés.

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
let fruitSamples = [
  [
    {'id': 1,'type': 'apples','samples': [1, 2, 3]},
    {'id': 2,'type': 'bananas','samples': [1, 2, 7]},
    {'id': 3,'type': 'pears','samples': [1, 2, 3]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [5, 2, 9]},
    {'id': 2,'type': 'bananas','samples': [1, 7, 7]},
    {'id': 3,'type': 'pears','samples': [12, 21, 32]}
  ],
  [
    {'id': 1,'type': 'apples','samples': [11, 2, 33]},
    {'id': 2,'type': 'bananas','samples': [17, 2, 67]},
    {'id': 3,'type': 'pears','samples': [91, 22, 34]}
  ]
];

function customizer(objValue, srcValue) {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
}

let test = _(fruitSamples)
  .flatten()
  .groupBy('type')
  .map(_.spread((...values) => {
    return _.mergeWith(...values, customizer);
  }))
  .value();
  
console.log(test);


1 commentaires

Même si j'ai utilisé la réponse no-lodash, cela m'a aidé à comprendre la fonction mergeWith. Je vous remercie.



0
votes

Une façon de le faire avec javascript et sans lodash:

var fruitSamples = [
[
   {'id': 1,'type': 'apples','samples': [1, 2, 3]},
   {'id': 2,'type': 'bananas','samples': [1, 2, 7]},
   {'id': 3,'type': 'pears','samples': [1, 2, 3]}
],
[
   {'id': 1,'type': 'apples','samples': [5, 2, 9]},
   {'id': 2,'type': 'bananas','samples': [1, 7, 7]},
   {'id': 3,'type': 'pears','samples': [12, 21, 32]}
],
[
   {'id': 1,'type': 'apples','samples': [11, 2, 33]},
   {'id': 2,'type': 'bananas','samples': [17, 2, 67]},
   {'id': 3,'type': 'pears','samples': [91, 22, 34]}
 ]
 ];

var test = fruitSamples.flat().reduce((rv,x)=>{
  var f = rv.find(y => y.id == x.id);
  if(f == null){
        f ={"id":x.id, "type":x.type,"samples":x.samples};
        rv.push(f);
  }
  else{
     f.samples = f.samples.concat(x.samples);
  }
  return rv;
},[]);
console.log(JSON.stringify(test))

https://jsfiddle.net/pimboden40/y8x96sbg/1/


0 commentaires