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 }]
4 Réponses :
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))
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);
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 :)
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
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)
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