按多个属性对对象进行分组并合并数组 属性
Group objects by multiple properties and merge array property
在示例中,我使用 each 通过 select 字段并创建数据数组,我需要将 2 个属性 year
和 cabin
以及 属性 months
是一个我想合并的数组,问题是我在获得想要的结果时遇到了一些麻烦:
JSFIDDLE:http://jsfiddle.net/tc39xu6b/2/
我得到的结果:
[
{
"year": "2021",
"cabin": "1",
"months": [
"1",
"2"
]
},
{
"year": "2021",
"cabin": "1",
"months": [
"4"
]
},
{
"year": "2021",
"cabin": "2",
"months": [
"1",
"2"
]
},
{
"year": "2022",
"cabin": "1",
"months": [
"1",
"2"
]
},
{
"year": "2022",
"cabin": "1",
"months": [
"4"
]
},
{
"year": "2022",
"cabin": "2",
"months": [
"1",
"2"
]
}
]
这就是我需要的结果:
{
"2021": [
{"cabin":1, "months": ["1", "2","4"]},
{"cabin":2, "months": ["1", "2"]}
],
"2022": [
{"cabin":1, "months": ["1", "2","4"]},
{"cabin":2, "months": ["1", "2"]}
]
}
那么,您已经找到了解决方案。
根据你所拥有的,我写了一个分组函数:
const addUnique=(arr1,arr2)=>{
arr2.forEach(item=>arr1.includes(item) || arr1.push(item))
return arr1;
}
const grouped= obj.reduce((groups,item)=>{
const yearItems=(groups[item.year]||[])
const cabinItem=yearItems.find(({cabin})=>cabin===item.cabin)
const newCabinItem=cabinItem||{cabin:item.cabin};
newCabinItem.months=addUnique(newCabinItem.months||[],item.months);
return {
...groups,
[item.year]: cabinItem
? yearItems.map(yearItem =>
yearItem.cabin === item.cabin
? newCabinItem
: yearItem)
: yearItems.concat([newCabinItem])
}
},{})
你可以看到它在这里工作:http://jsfiddle.net/9huwkz5L/
这是一个相当标准的 group by
情况。下面的代码片段使用 reduce()
来重构您的数组,但您可以将逻辑直接放在您的函数中:http://jsfiddle.net/83st9wgh/
const input = [{ "year": "2021", "cabin": "1", "months": ["1", "2"] }, { "year": "2021", "cabin": "1", "months": ["4"] }, { "year": "2021", "cabin": "2", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["4"] }, { "year": "2022", "cabin": "2", "months": ["1", "2"] }];
const result = input.reduce((acc, { year, cabin, months }) => {
const yearArray = (acc[year] ??= []);
let cIndex = yearArray.findIndex(o => o.cabin === cabin);
if (cIndex === -1) {
cIndex = yearArray.push({ cabin, months: [] }) - 1;
}
const monthsArray = yearArray[cIndex].months;
yearArray[cIndex].months = [...new Set(monthsArray.concat(months))];
return acc;
}, {});
console.log(JSON.stringify(result, null, 2));
在示例中,我使用 each 通过 select 字段并创建数据数组,我需要将 2 个属性 year
和 cabin
以及 属性 months
是一个我想合并的数组,问题是我在获得想要的结果时遇到了一些麻烦:
JSFIDDLE:http://jsfiddle.net/tc39xu6b/2/
我得到的结果:
[
{
"year": "2021",
"cabin": "1",
"months": [
"1",
"2"
]
},
{
"year": "2021",
"cabin": "1",
"months": [
"4"
]
},
{
"year": "2021",
"cabin": "2",
"months": [
"1",
"2"
]
},
{
"year": "2022",
"cabin": "1",
"months": [
"1",
"2"
]
},
{
"year": "2022",
"cabin": "1",
"months": [
"4"
]
},
{
"year": "2022",
"cabin": "2",
"months": [
"1",
"2"
]
}
]
这就是我需要的结果:
{
"2021": [
{"cabin":1, "months": ["1", "2","4"]},
{"cabin":2, "months": ["1", "2"]}
],
"2022": [
{"cabin":1, "months": ["1", "2","4"]},
{"cabin":2, "months": ["1", "2"]}
]
}
那么,您已经找到了解决方案。
根据你所拥有的,我写了一个分组函数:
const addUnique=(arr1,arr2)=>{
arr2.forEach(item=>arr1.includes(item) || arr1.push(item))
return arr1;
}
const grouped= obj.reduce((groups,item)=>{
const yearItems=(groups[item.year]||[])
const cabinItem=yearItems.find(({cabin})=>cabin===item.cabin)
const newCabinItem=cabinItem||{cabin:item.cabin};
newCabinItem.months=addUnique(newCabinItem.months||[],item.months);
return {
...groups,
[item.year]: cabinItem
? yearItems.map(yearItem =>
yearItem.cabin === item.cabin
? newCabinItem
: yearItem)
: yearItems.concat([newCabinItem])
}
},{})
你可以看到它在这里工作:http://jsfiddle.net/9huwkz5L/
这是一个相当标准的 group by
情况。下面的代码片段使用 reduce()
来重构您的数组,但您可以将逻辑直接放在您的函数中:http://jsfiddle.net/83st9wgh/
const input = [{ "year": "2021", "cabin": "1", "months": ["1", "2"] }, { "year": "2021", "cabin": "1", "months": ["4"] }, { "year": "2021", "cabin": "2", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["4"] }, { "year": "2022", "cabin": "2", "months": ["1", "2"] }];
const result = input.reduce((acc, { year, cabin, months }) => {
const yearArray = (acc[year] ??= []);
let cIndex = yearArray.findIndex(o => o.cabin === cabin);
if (cIndex === -1) {
cIndex = yearArray.push({ cabin, months: [] }) - 1;
}
const monthsArray = yearArray[cIndex].months;
yearArray[cIndex].months = [...new Set(monthsArray.concat(months))];
return acc;
}, {});
console.log(JSON.stringify(result, null, 2));