Javascript 数组如何按两个属性分组?
Ex:Javascript 数组如何按两个属性分组?,javascript,arrays,ecmascript-6,Javascript,Arrays,Ecmascript 6,Ex: const arr = [{ group: 1, question: { templateId: 100 } }, { group: 2, question: { templateId: 200 } }, { group: 1, question: { templateId: 100 } }, { group: 1, question: { templateId: 300 } }]; 预期结果:const
const arr = [{
group: 1,
question: {
templateId: 100
}
}, {
group: 2,
question: {
templateId: 200
}
}, {
group: 1,
question: {
templateId: 100
}
}, {
group: 1,
question: {
templateId: 300
}
}];
预期结果:const Result=groupBy(arr,'group','question.templateId')代码>
到目前为止:我可以使用单个属性对结果进行分组
功能分组依据(arr,键){
返回[…arr.reduce((累加器,当前值)=>{
const propVal=当前值[键],
组=累加器.get(propVal)| |[];
分组推送(currentValue);
返回累加器.set(propVal,group);
},新映射())。值()];
}
常数arr=[{
组别:1,,
问题:{
模板ID:100
}
}, {
组别:2,,
问题:{
模板ID:200
}
}, {
组别:1,,
问题:{
模板ID:100
}
}, {
组别:1,,
问题:{
模板ID:300
}
}];
const result=groupBy(arr,'group');
控制台日志(结果)代码>我建议传递回调函数而不是属性名,这样可以轻松地进行两级访问:
function groupBy(arr, key) {
return Array.from(arr.reduce((accumulator, currentValue) => {
const propVal = key(currentValue),
// ^^^^ ^
group = accumulator.get(propVal) || [];
group.push(currentValue);
return accumulator.set(propVal, group);
}, new Map()).values());
}
现在您可以执行groupBy(arr,o=>o.group)
和groupBy(arr,o=>o.question.templateId)
要获得预期结果,只需按第一个属性分组,然后按第二个属性分组每个结果:
function concatMap(arr, fn) {
return [].concat(...arr.map(fn));
}
const result = concatMap(groupBy(arr, o => o.group), res =>
groupBy(res, o => o.question.templateId)
);
@如果您可以对输入进行硬编码,那么Bergi的答案非常好
如果要使用字符串输入,可以使用sort()
方法,并根据需要遍历对象
此解决方案将处理任意数量的参数:
功能分组依据(arr){
var arg=参数;
返回arr.sort((a,b)=>{
var i、key、aval、bval;
对于(i=1;ibval)返回1;
}
返回0;
});
}
常数arr=[{
组别:1,,
问题:{
模板ID:100
}
}, {
组别:2,,
问题:{
模板ID:200
}
}, {
组别:1,,
问题:{
模板ID:100
}
}, {
组别:1,,
问题:{
模板ID:300
}
}];
const result=groupBy(arr,'group','question.templateId');
控制台日志(结果)代码>@Bergi的答案非常实用,但我将向您展示如何使用JavaScript原语构建多值“键”——不要认为这意味着Bergi的答案在任何方面都不好;事实上,由于它的实用性,它实际上要好得多。如果有什么问题的话,这个答案的存在是为了告诉你使用像他的方法可以节省多少工作量
我将一点一点地检查代码,然后在最后有一个完整的可运行演示
复合数据相等性
比较JavaScript中的复合数据有点棘手,因此我们需要首先找到一种解决方法:
console.log([1,2]=[1,2])//false
非常感谢Naomik为您的回答所做的努力和出色的解释。一步一步的解释非常清晰、一致和友好——它确实帮助我更好地理解了我的需求本身,以及如何用不同的方法解决它。一个+1
是不够的,所以再次感谢:)
。瑞奇,我很高兴能帮上忙^^哇,非常彻底
function concatMap(arr, fn) {
return [].concat(...arr.map(fn));
}
const result = concatMap(groupBy(arr, o => o.group), res =>
groupBy(res, o => o.question.templateId)
);