1
votes

fusionner des tableaux partiellement dupliqués en javascript (lodash)

J'ai un grand nombre de personnes javascript qui ont acheté une voiture au cours des années. le tableau simplifié est comme ceci:

const owners = [{
  name: "john",
  hasCar: true,
  yearBought: [2002, 2005, 2018]
}, {
  name: "mary",
  hasCar: true,
  yearBought: 2018
}]

si une personne a plus d'une voiture (comme John dans cet exemple), il y a différents objets pour lui avec différentes années où il a acheté la voiture. Je veux fusionner des objets appartient à chaque personne et le résultat final devrait être comme ceci:

const owners = [{
  name: "john",
  hasCar: true,
  yearBought: 2002
}, {
  name: "john",
  hasCar: true,
  yearBought: 2005
}, {
  name: "mary",
  hasCar: true,
  yearBought: 2015
}, {
  name: "john",
  hasCar: true,
  yearBought: 2018
}]


1 commentaires

Je ne pense pas que vous ayez besoin de Lodash pour ça. Il suffit de vérifier si l'élément avec le nom donné existe et si oui, de pousser les années à yearsBought , s'il n'existe pas, il suffit de pousser le nouvel élément dans la liste


4 Réponses :


1
votes

Vous pouvez utiliser réduire le tableau et regroupez-les d'abord en fonction du nom . L'accumulateur est un objet avec chaque nom unique comme clé. Si le nom existe déjà, utilisez concat pour les pousser dans le tableau. Sinon, créez une nouvelle clé dans l'accumulateur et définissez-la sur l'objet actuel. Ensuite, utilisez Object.values ​​( ) pour obtenir les valeurs du tableau sous forme de tableau

const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}];

const merged = owners.reduce((r, o) => {
  if(r[o.name])
    r[o.name].yearBought = [].concat(r[o.name].yearBought, o.yearBought)
  else
    r[o.name] = { ...o };
  return r;
},{})

console.log(Object.values(merged))


0 commentaires

0
votes

Utilisez simplement reduce:

const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:true,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}];

const newOwners = Object.values(owners.reduce((acc, curr) => {
  acc[curr.name] = acc[curr.name] ? { ...acc[curr.name], yearBought: [].concat(acc[curr.name].yearBought, curr.yearBought) } : curr;
  return acc;
}, {}));

console.log(newOwners);


0 commentaires

0
votes

J'espère que cette aide en utilisant les fonctions PURE lodash .. elle semble propre et lisible.

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
var array = [{
  name: "john",
  hasCar: true,
  yearBought: 2002
}, {
  name: "john",
  hasCar: true,
  yearBought: 2005
}, {
  name: "mary",
  hasCar: true,
  yearBought: 2015
}, {
  name: "john",
  hasCar: true,
  yearBought: 2018
}]

function mergeNames(arr) {
  return Object.values(_.chain(arr).groupBy('name').mapValues((g) => (_.merge(...g, {
    yearBought: _.map(g, 'yearBought')
  }))).value());
}
console.log(mergeNames(array));

Merci :)


2 commentaires

Cela crée également un tableau yearBought pour mary


Je crois que cela devrait être cohérent pour chaque cas, c'est-à-dire dans lequel nous avons une valeur unique ou plusieurs valeurs pour yearBought . De cette façon, vous pouvez le gérer facilement



0
votes

Vous pouvez regrouper les éléments avec une clé unique ( nom dans votre cas), puis mapper les groupes et fusionner les éléments de chaque groupe:

<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
const { flow, groupBy, map, mergeAllWith, cond, nthArg, concat } = _

const mergeDuplicates = (isCollected, key) => flow(
  groupBy(key),
  map(mergeAllWith(cond([[
    flow(nthArg(2), isCollected),
    concat,
    nthArg(1)
  ]])))
)

const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}]

const isCollected = key => key === 'yearBought'

const result = mergeDuplicates(isCollected, 'name')(owners)

console.log(result)

Et la version lodash / fp:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
const { flow, partialRight: pr, groupBy, map, mergeWith, concat, isUndefined } = _

const mergeDuplicates = (isCollected, key) => flow(
  pr(groupBy, key), // group by the unique key
  pr(map, group => mergeWith({}, ...group, 
    (o, s, k) => isCollected(k) && !isUndefined(o) ? concat(o, s) : s
  )) // merge each group to a new object
)

const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}]

const isCollected = key => key === 'yearBought'

const result = mergeDuplicates(isCollected, 'name')(owners)

console.log(result)


0 commentaires