[英]How to merge objects with the same properties into a single Array?
I'm reciving the next data 我正在收到下一个数据
[
{ id: "1", name: "test1", rName: "the1" },
{ id: "1", name: "test1", rName: "the2" },
{ id: "1", name: "test1", rName: "the3" },
{ id: "2", name: "test2", rName: "the1" },
{ id: "2", name: "test2", rName: "the2" },
{ id: "3", name: "test3", rName: "the1" }
]
I want to merge it by the id and push the rName's into an array to have this structure 我想通过id合并它并将rName推入一个数组以获得这个结构
[
{ id: "1", name: "test1", rName: ["the1", "the2","the3"] },
{ id: "2", name: "test2", rName: ["the1", "the2"] },
{ id: "3", name: "test3", rName: ["the1"] }
]
I thought doing it with reduce but didn't succeed, if anyone can point me to the right direction it will be greatly appreciated. 我认为这样做会减少,但没有成功,如果有人能指出我正确的方向,将不胜感激。
This is a pretty simple case of data reformatting. 这是一个非常简单的数据重新格式化案例。 Code is below.
代码如下。
var data = [ { id: "1", name: "test1", rName: "the1" }, { id: "1", name: "test1", rName: "the2" }, { id: "1", name: "test1", rName: "the3" }, { id: "2", name: "test2", rName: "the1" }, { id: "2", name: "test2", rName: "the2" }, { id: "3", name: "test3", rName: "the1" } ]; var reduced = Object.values(data.reduce(function(accumulator, element) { if (!accumulator[element.id]) { accumulator[element.id] = { id: element.id, name: element.name, rName: [] }; } accumulator[element.id].rName.push(element.rName); return accumulator; }, {})); console.log(reduced);
The accumulator checks if the key by element.id
exists in the accumulator. 累加器检查按
element.id
中的键是否存在于累加器中。 If it does not, it creates it. 如果没有,则创建它。 It then pushes the new
rName
on the existing stack. 然后它在现有堆栈上推送新的
rName
。 Object.values()
is then used to make the conversion back to an array. 然后使用
Object.values()
将转换返回到数组。
You can use reduce
and find
like this: 您可以使用
reduce
并find
如下:
In the reduce accumulator
, check if there is already an item with same id
as the current item being iterated. 在reduce
accumulator
,检查是否已存在与正在迭代的当前项具有相同id
的项。 If yes, push the current item's rName
to the rName
array. 如果是,请将当前项的
rName
推送到rName
数组。 Else, push a new item to the accumulator
否则,将新项目推送到
accumulator
var data = [ { id: "1", name: "test1", rName: "the1" }, { id: "1", name: "test1", rName: "the2" }, { id: "1", name: "test1", rName: "the3" }, { id: "2", name: "test2", rName: "the1" }, { id: "2", name: "test2", rName: "the2" }, { id: "3", name: "test3", rName: "the1" } ]; const newArray = data.reduce((acc, {id,name,rName}) => { const existing = acc.find(a => a.id == id); if (existing) existing["rName"].push(rName); else acc.push({id,name,rName: [rName]}) return acc }, []); console.log(newArray)
This is a one line, code-golf answer. 这是一个代码高尔夫的答案。 (Got the idea from @Sébastien's answer):
(从@Sébastien的回答中得到了想法):
var data = [ { id: "1", name: "test1", rName: "the1" }, { id: "1", name: "test2", rName: "the2" }, { id: "1", name: "test2", rName: "the3" }, { id: "2", name: "test2", rName: "the1" }, { id: "2", name: "test1", rName: "the2" }, { id: "3", name: "test3", rName: "the1" } ] const anotherArray = Object.values(data.reduce((acc, {id,name,rName}) => ((acc[id] = acc[id] || {id,name,rName:[]})["rName"].push(rName), acc), {})); console.log(anotherArray)
Pure ES6 纯ES6
let result = obj.reduce((acc, item) => {
let found = acc.find(i => i.id === item.id);
found ? (found.rName = [...found.rName, item.rName]) : (acc = [...acc, { ...item, rName: [item.rName] }]);
return acc;
}, []);
If each id
can determine a unique name
, this will work: 如果每个
id
都可以确定唯一的name
,那么这将起作用:
let data = [
{ id: "1", name: "test1", rName: "the1" },
{ id: "1", name: "test1", rName: "the2" },
{ id: "1", name: "test1", rName: "the3" },
{ id: "2", name: "test2", rName: "the1" },
{ id: "2", name: "test2", rName: "the2" },
{ id: "3", name: "test3", rName: "the1" }
];
let result = [];
for (let item of data)
{
const index = result.findIndex(i => i.id === item.id);
if (index < 0) {
result.push({ id: item.id, name: item.name, rName: [item.rName] });
}
else {
result[index].rName.push(item.rName);
}
}
Please note this will not work when following data should accept: 请注意,当以下数据接受时,这将不起作用:
[
{ id: "1", name: "test1", rName: "the1" },
{ id: "1", name: "test2", rName: "the2" },
{ id: "1", name: "test2", rName: "the3" },
{ id: "2", name: "test2", rName: "the1" },
{ id: "2", name: "test1", rName: "the2" },
{ id: "3", name: "test3", rName: "the1" }
]
If you adhere to use method 'reduce', you can do like this: 如果你坚持使用'reduce'方法,你可以这样做:
var arr = [
{ id: "1", name: "test1", rName: "the1" },
{ id: "1", name: "test1", rName: "the2" },
{ id: "1", name: "test1", rName: "the3" },
{ id: "2", name: "test2", rName: "the1" },
{ id: "2", name: "test2", rName: "the2" },
{ id: "3", name: "test3", rName: "the1" }
]
var arr1 = arr.reduce(function (a1, a2) {
if (a1 instanceof Array) {
let lastItem = a1[a1.length - 1]
if (lastItem.id == a2.id) {
lastItem.rName.push(a2.rName)
} else {
a1.push({ ...a2, rName: [a2.rName] })
}
return a1
} else {
let result = []
if (a1.id == a2.id) {
result.push({ ...a1, rName: [a1.rName, a2.rName] })
} else {
result.push({ ...a1, rName: [a1, rName] })
result.push({ ...a2, rName: [a2, rName] })
}
return result
}
})
console.log(JSON.stringify(arr1))
But I think you should do like this, for the code is more clear: 但我认为你应该这样做,因为代码更清晰:
var arr = [
{ id: "1", name: "test1", rName: "the1" },
{ id: "1", name: "test1", rName: "the2" },
{ id: "1", name: "test1", rName: "the3" },
{ id: "2", name: "test2", rName: "the1" },
{ id: "2", name: "test2", rName: "the2" },
{ id: "3", name: "test3", rName: "the1" }
]
var map = new Map()
arr.forEach(function(item){
if(map.has(item.id)){
map.get(item.id).rName.push(item.rName)
}else{
map.set(item.id, {...item, rName: [item.rName]})
}
})
var arr1 = Array.from(map.values())
console.log(JSON.stringify(arr1))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.