这是一个有点棘手的找到正确的词,所以希望展示一些代码将有所帮助。
我有以下(简化)人员和他们的部门的数组。这来自于CMS数据,它允许将一个人添加到多个部门(因此departments是一个数组)。
[
{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
},
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
},
{
id: '00099',
name: 'Person 4',
jobTitle: 'No department',
departments: []
}
]我所追求的结果是获得departments的唯一值,并为每个数组创建数组,其中包含适当的用户,如下所示:
{
'Engineering': [
{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
}
],
'Leadership': [
{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
}
]
}我的代码中已经有了一个groupBy函数,但它并不完全满足我的要求(因为它并不期望数组作为属性值),所以如果一个person有多个部门,我会得到一个数组,其中两个部门的名称都是串联的,但是我希望在多个数组中出现相同的person。
这是我目前的groupBy函数,但现在它分散了我的注意力,而reduce是一个我的大脑一直在挣扎的概念.!
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
// which I can use like:
const groupedPeople = Object.entries(groupBy(people, "departments"));
// and it'll return
/*
{
'Engineering,Leadership': [
{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
}
],
'Engineering': [
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
}
],
'Leadership': [
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
}
]
}
*/我觉得我离得很近了,但我的大脑无法投入其中!
const people = [{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
},
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
},
{
id: '00099',
name: 'Person 4',
jobTitle: 'No department',
departments: []
}
]
function groupBy(objectArray, property) {
return objectArray.reduce(function(acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
// which I can use like:
const groupedPeople = Object.entries(groupBy(people, "departments"));
console.log("Grouped:", groupedPeople);
发布于 2022-04-21 21:40:30
var key = obj[property];在代码的这一行中,key变量表示deparments数组,然后将其用作acc[key]。JS是如何将数组转换成字符串作为acc对象的键的,这是通过逗号加入数组的过程。您需要的是遍历数组,而不是:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var keys = obj[property];
keys.forEach(key => {
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
})
return acc;
}, {});
}这种更改将使其对您的用例有效,如果键不是数组,则groupBy函数将不再工作,因此谨慎使用或使其既支持字符串又支持数组。
发布于 2022-04-21 21:44:21
我在我的解决方案中得到了一个递归错误,在将它推入两个不同的数组之前,我不得不对一个对象(JSON.parse(JSON.stringify(obj)))进行深度复制。此外,考虑到您的属性可能是数组,也可能不是数组,我将该部分规范化为:
let keys = Array.isArray(obj[property]) ? obj[property] : [obj[property]];
let people = [{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
},
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
},
{
id: '00099',
name: 'Person 4',
jobTitle: 'No department',
departments: []
}
];
function groupBy(objectArray, property) {
return objectArray.reduce((acc, obj) => {
let keys = Array.isArray(obj[property]) ? obj[property] : [obj[property]];
keys.forEach(k => {
acc[k] = acc[k] || [];
acc[k].push(JSON.parse(JSON.stringify(obj)))
})
return acc;
}, {});
}
console.log(groupBy(people, "departments"));
console.log(groupBy(people, "jobTitle"));
发布于 2022-04-21 21:55:33
我只更改了3行代码片段,首先将所有内容转换为数组,然后遍历该数组并创建组使代码更容易编写。您还可以检查它是否是数组,并使用if语句编写类似的代码。
const people = [{
id: '12345',
name: 'Person 1',
jobTitle: 'Engineering director',
departments: ['Engineering', 'Leadership']
},
{
id: '54321',
name: 'Person 2',
jobTitle: 'Junior engineer',
departments: ['Engineering']
},
{
id: '00001',
name: 'Person 3',
jobTitle: 'Founder',
departments: ['Leadership']
},
{
id: '00099',
name: 'Person 4',
jobTitle: 'No department',
departments: []
}
]
function groupBy(objectArray, property) {
return objectArray.reduce(function(acc, obj) {
if (obj[property] === null || obj[property] === undefined) return acc; // if obj[property] is not defined or it's null don't add it to groupts
if (obj[property].constructor !== Array) obj[property] = [obj[property]] // obj[property] is always an array now
obj[property].forEach(key => {
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
})
return acc;
}, {});
}
// which I can use like:
const groupedPeople = Object.entries(groupBy(people, "departments"));
console.log("Grouped:", groupedPeople);
https://stackoverflow.com/questions/71961069
复制相似问题