#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня есть массив объектов следующим образом
[
0: {department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, …}
1: {department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, …}
2: {department_ID: 1, department_Name: "HR amp; Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, …}
...
]
Чего я хочу добиться, так это группировать значения в массиве по порядку одинаковые department_ID
> одинаковые section_ID
и, наконец, данные сотрудника, подобные этому
[
{
department_ID: 6,
department_Name: "Management",
children: [
{
section_ID: 12,
section_Name: "General Management",
children: [
{
employee_ID: 1,
employee_Name: "",
},
{
employee_ID: 2,
employee_Name: "",
},
],
},
],
},
{
department_ID: 1,
department_Name: "HR amp; Admin",
children: [
{
section_ID: 20,
section_Name: "HR and Admin",
children: [
{
employee_ID: 90,
employee_Name: "",
},
],
},
],
},
];
Я пробовал
function getUnique() {
var hashObject = {};
let obj = {};
treeviewApiValues.forEach(function (elem) {
var key = elem.department_ID;
if (hashObject[key]) {
hashObject[key] = {
id: elem.department_ID,
name: elem.department_Name,
children: checkSectionID(elem),
};
} else {
hashObject[key] = {
id: elem.department_ID,
name: elem.department_Name,
children: checkSectionID(elem),
};
}
});
function checkSectionID(elem) {
const key = elem.department_ID;
if (obj[key]) {
obj[key].push({
id: elem.section_ID,
name: elem.section_Name,
});
} else {
obj[key] = [
{
id: elem.section_ID,
name: elem.section_Name,
},
];
}
var desiredArray2 = Object.values(obj);
return desiredArray2;
}
var desiredArray = Object.values(hashObject);
}
Это грязная функция, но я получаю
[
0: {department_ID: 1, department_Name: "HR amp; Admin", children: Array(7)}
1: {department_ID: 2, department_Name: "ELV Systems Installation amp; Service", children: Array(7)}
]
Дочерний массив — это что-то неправильное, и у него нет массива с одинаковым идентификатором department_ID, и мне также нужно получить данные сотрудника в том же section_ID.
Если бы кто-нибудь мог мне помочь, я был бы очень признателен.
Полный код можно найти здесь https://codesandbox.io/s/gracious-voice-bbmsy?file=/src/App.js
Ответ №1:
Вы могли бы использовать вложенный подход с массивом для уровней группировки.
Это решение удаляет нежелательные свойства объекта и помещает конечный объект в самый вложенный дочерний массив.
Это решение работает для произвольного количества уровней.
const
data = [{ department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1 }, { department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2 }, { department_ID: 1, department_Name: "HR amp; Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90 }],
groups = [['department_ID', 'department_Name'], ['section_ID', 'section_Name']],
result = data.reduce((r, o) => {
groups
.reduce((group, keys) => {
let temp = group.find(q => q[keys[0]] === o[keys[0]]);
if (!temp) group.push(temp = { ...Object.fromEntries(keys.map(k => [k, o[k]])), children: [] });
keys.forEach(k => ({ [k]: _, ...o} = o));
return temp.children;
}, r)
.push(o);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Комментарии:
1. Это именно то, что мне было нужно! Большое спасибо. Однако, когда я тестирую,
_
отображается undefined. Я думаю, вы забыли добавитьkeys.forEach((k, _) => ..)
, спасибо в любом случае2. нет, потому
_
что это заполнитель для именованного свойства, которое больше не нужно.
Ответ №2:
Может быть, это решит вашу задачу
let list = [
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, …},
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, …},
{department_ID: 1, department_Name: "HR amp; Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, …}
...
];
let vals = [];
list.map(v=>{
vals[v.department_ID] || (vals[v.department_ID] = {
department_ID: v.department_ID,
department_Name: v.department_Name,
children: []
});
vals[v.department_ID].children[v.section_ID] ||
(vals[v.department_ID].children[v.section_ID] = {
section_ID: v.section_ID,
section_Name: v.section_Name,
children: []
});
vals[v.department_ID].children[v.section_ID].children.push({
employee_ID: v.employee_ID,
employee_Name: v.employee_Name
});
});
vals = vals.filter(e=>!!e);
let result = vals.map(e=>{
e.children = e.children.filter(v=>!!v);
return e;
});
Ответ №3:
Вы можете использовать reduce()
и find()
следующим образом:
const arr = [
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, employee_name: 'john'},
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, employee_name: 'avi'},
{department_ID: 1, department_Name: "HR amp; Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, employee_name: 'jennifer'}
]
const res = arr.reduce((acc, curr) => {
const obj = acc.find(item => item.department_ID === curr.department_ID amp;amp; item?.children[0]?.section_ID === curr.section_ID);
if(obj) {
obj.children[0].children.push({ employee_ID: curr.employee_ID, employee_name: curr.employee_name});
} else {
acc.push({
department_ID: curr.department_ID,
department_Name: curr.department_Name,
children: [
{
section_ID: curr.section_ID,
section_Name: curr.section_Name,
children: [{
employee_ID: curr.employee_ID,
employee_name: curr.employee_name
}]
}
]
})
}
return acc;
}, []);
console.log(res);