Merge specific properties of objects together with JavaScript

亡梦爱人 提交于 2020-02-16 11:30:12

问题


So I have an array of objects like so:

[
  {
    name: "Joe Smith",
    job: "Janitor",
    age: 35,
    id: "3421"
  },
  {
    name: "George Henderson",
    job: "CEO",
    age: 43,
    id: "5098"
  },
  {
    name: "Joe Smith",
    job: "Cook",
    age: 35,
    id: "3421"
  },
  {
    name: "Sam Doe",
    job: "Technician",
    age: 22,
    id: "1538"
  },
  {
    name: "Joe Smith",
    job: "Dishwasher",
    age: 35,
    id: "3421"
  } 
]

As you can see, Joe Smith has three jobs. What I want to do is to combine all of his jobs into one object like so:

{
   name: "Joe Smith",
   job: "Janitor, Cook, Dishwasher",
   age: 35,
   id: "3421"
}

I'd like to be able to do this with any person who has multiple jobs. Also, there could be multiple people with the same name, so it would be better to identify the people by their id, not name.

How would I go about doing this? Using a library like Lodash is great if it simplifies the code, but I can't think of a simpler way than iterating through the array, but that can get complex.

Thanks!


回答1:


With lodash, you could group the array and map the wanted properties.

var data = [{ name: "Joe Smith", job: "Janitor", age: 35, id: "3421" }, { name: "George Henderson", job: "CEO", age: 43, id: "5098" }, { name: "Joe Smith", job: "Cook", age: 35, id: "3421" }, { name: "Sam Doe", job: "Technician", age: 22, id: "1538" }, { name: "Joe Smith", job: "Dishwasher", age: 35, id: "3421" }],
    result = _(data)
        .groupBy('id')
        .map(array => ({ ...array[0], job: _.join(_.map(array, 'job'), ", ") }))
        .value();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>



回答2:


By using reduce to iterate through the array to build a new one, and simply check if the id is already inserted then concatenate the job otherwise insert the new object:

const arr = [
  { name: "Joe Smith", job: "Janitor", age: 35, id: "3421" },
  { name: "George Henderson", job: "CEO", age: 43, id: "5098" },
  { name: "Joe Smith", job: "Cook", age: 35, id: "3421" },
  { name: "Sam Doe", job: "Technician", age: 22, id: "1538" },
  { name: "Joe Smith", job: "Dishwasher", age: 35, id: "3421" } 
]

const result = arr.reduce((acc, cur) => {
    const duplicate = acc.find(e => e.id == cur.id)
    
    if (duplicate) {
	duplicate.job += ', ' + cur.job
    } else {
	acc.push(cur)
    }

    return acc
}, [])

console.log(result)



回答3:


I would suggest using a temporary Map, so to avoid having to iterate each time to find whether the name is a duplicate (like with find).

Also, it seems better practice to let the multiple values of job be put in an array:

let data = [{name: "Joe Smith",job: "Janitor",age: 35,id: "3421"},{name: "George Henderson",job: "CEO",age: 43,id: "5098"},{name: "Joe Smith",job: "Cook",age: 35,id: "3421"},{name: "Sam Doe",job: "Technician",age: 22,id: "1538"},{name: "Joe Smith",job: "Dishwasher",age: 35,id: "3421"}];

let map = new Map(data.map(({name, job, age, id}) => [id, { name, job: [], age, id}]));
data.forEach(o => map.get(o.id).job.push(o.job));
let result = Array.from(map.values());

console.log(result);

If you really want to join the job arrays as comma separated values, then apply join(", ") on them, but I would go for the array.



来源:https://stackoverflow.com/questions/60010920/merge-specific-properties-of-objects-together-with-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!