JavaScript - 按键减少对象数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51935559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript - Reduce Array of Objects by Key
提问by proph3t
Working with an array of objects like:
使用一组对象,例如:
const arr = [
{name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
{name: "survey with select", value: "survey with select answer", count: 2},
{name: "werasd", value: "Donald", count: 1},
{name: "werasd", value: "Jim", count: 1}
];
I am trying to reduce the array on matching values for the namekey and achieve an desired output like:
我正在尝试减少name键匹配值的数组并实现所需的输出,例如:
desiredOutput = [
{name: "qewregf dqewafs", data: [{value: "qewregf dqewafs answer", count: 2}]},
{name: "survey with select", data: [{value: "survey with select answer", count: 2}]},
{name: "werasd", data: [{value: "Donald", count: 1}, {value: "Jim", count: 1}]}
]
This attempt reduces the array, but I am missing how to merge the nested values without overwriting.
这种尝试减少了数组,但我缺少如何在不覆盖的情况下合并嵌套值。
const arr = [{"name":"qewregf dqewafs","value":"qewregf dqewafs answer","count":2},{"name":"survey with select","value":"survey with select answer","count":2},{"name":"werasd","value":"Donald","count":1},{"name":"werasd","value":"Jim","count":1}];
const result = arr.reduce((acc, d) => {
const found = acc.find(a => a.name === d.name);
const value = { name: d.name, val: d.value };
if (found) {
acc.push(...value);
}
else {
acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
}
return acc;
}, []);
console.log(result);
What am I missing?
我错过了什么?
回答by Sphinx
You codes are a little close to the goal, just need to adjust something.
你的代码有点接近目标,只需要调整一些东西。
Please see the comment in below demo:
请参阅以下演示中的评论:
When
acc.finddoesn't find anything, then push one element{name:d.name, data: [value]}if found, then push one
{value: ...}into data property.
当
acc.find没有找到任何东西时,则推送一个元素{name:d.name, data: [value]}如果找到,则将其推
{value: ...}入数据属性。
const arr = [
{name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
{name: "survey with select", value: "survey with select answer", count: 2},
{name: "werasd", value: "Donald", count: 1},
{name: "werasd", value: "Jim", count: 1}
];
const result = arr.reduce((acc, d) => {
const found = acc.find(a => a.name === d.name);
//const value = { name: d.name, val: d.value };
const value = { value: d.value, count: d.count }; // the element in data property
if (!found) {
//acc.push(...value);
acc.push({name:d.name, data: [value]}) // not found, so need to add data property
}
else {
//acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
found.data.push(value) // if found, that means data property exists, so just push new element to found.data.
}
return acc;
}, []);
console.log(result)
回答by amrender singh
Simply create a map with name as key and use Object destructingand Object.values()to get the desired result.
只需创建一个以名称为键的地图,然后使用Object destructing和Object.values()即可获得所需的结果。
const arr = [
{name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
{name: "survey with select", value: "survey with select answer", count: 2},
{name: "werasd", value: "Donald", count: 1},
{name: "werasd", value: "Jim", count: 1}
];
let result = Object.values(arr.reduce((a,{name, ...props})=>{
if(!a[name])
a[name] = Object.assign({}, {name,data : [props]});
else
a[name].data.push(props);
return a;
},{}));
console.log(result);
回答by Nina Scholz
You could simplify the use of the found object by checking if it does not exist and push a new object to the result set.
您可以通过检查找到的对象是否不存在并将新对象推送到结果集来简化其使用。
Then push an object with valueand countto data.
然后按一个对象与value和count给data。
const
array = [{ name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2 }, { name: "survey with select", value: "survey with select answer", count: 2 }, { name: "werasd", value: "Donald", count: 1 }, { name: "werasd", value: "Jim", count: 1 }],
result = array.reduce((r, { name, value, count }) => {
var temp = r.find(o => name === o.name);
if (!temp) {
r.push(temp = { name, data: [] });
}
temp.data.push({ value, count });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
回答by WakeskaterX
You need to do something like this:
你需要做这样的事情:
const arr = [
{name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
{name: "survey with select", value: "survey with select answer", count: 2},
{name: "werasd", value: "Donald", count: 1},
{name: "werasd", value: "Jim", count: 1}
];
const result = arr.reduce((acc, d) => {
let idx = acc.findIndex(a => a.name === d.name);
let val = { value: d.value, count: d.count };
if (idx > -1) {
acc[idx].data.push(val);
} else {
acc.push({ name: d.name, data: [val] });
}
return acc;
}, []);
console.log(result);
You have to find the index first, and then push your data into that row. You're just finding it but then pushing a new value to the array.
您必须先找到索引,然后将数据推送到该行中。您只是找到它,然后将新值推送到数组。
回答by Scott Sauyet
You're not far off. This would be a simple change to two lines of your code to achieve it:
你离得不远了。这将是对两行代码的简单更改以实现它:
const arr = [
{name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
{name: "survey with select", value: "survey with select answer", count: 2},
{name: "werasd", value: "Donald", count: 1},
{name: "werasd", value: "Jim", count: 1}
];
const result = arr.reduce((acc, d) => {
const found = acc.find(a => a.name === d.name);
const value = { name: d.name, val: d.value };
if (found) {
found.data.push(value);
}
else {
acc.push({ name: d.name, data: [{ value: d.value, count: d.count }] });
}
return acc;
}, []);
console.log(result)
Here are the differences:
以下是差异:
- acc.push(...value);
+ found.data.push(value);
- acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
+ acc.push({ name: d.name, data: [{ value: d.value, count: d.count }] });

