问题
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