У меня есть рекурсивный способ, который может обрабатывать более глубокое вложение и т. Д. c., Который, кажется, не нужен вам (?), Но он есть, если вы этого хотите. Если вам нужен только 1 уровень глубины, то мы также можем упростить его.
const input = [
{id: 0, section: ['valueX']},
{id: 1, section: ['valueX']},
{id: 2, section: ['valueY']},
{id: 3, section: ['valueY', 'valueX', 'valueZ']},
{id: 4, section: []}
];
const groupBy = (input, propertyArr) => {
//console.log(propertyArr);
const property = propertyArr[0];
const grouped = input.reduce((groupedObj, item) => {
const key = item[property];
if (key instanceof Array && key.length > 0){
key.forEach(k => {
groupedObj[k] = [...(groupedObj[k] || []), item];
})
}else if (key instanceof Array){
groupedObj['all'] = [...(groupedObj['all'] || []), item];
}else{
groupedObj[key] = [...(groupedObj[key] || []), item];
}
return groupedObj;
}, {});
if (propertyArr.length > 1) {
//console.log(grouped);
return Object.keys(grouped).reduce((AggObj, key, index) => {
const propertyArrCopy = [...propertyArr];
propertyArrCopy.shift();
AggObj[key] = groupBy(grouped[key], propertyArrCopy);
return AggObj;
}, {});
}else {
return grouped;
}
};
const grouped = groupBy(input, ["section"]);
console.log(grouped);
const inputNested = [
{id: 0, somekey: 'someValA', section: ['valueX']},
{id: 1, somekey: 'someValB', section: ['valueX']},
{id: 2, somekey: 'someValA', section: ['valueY']},
{id: 3, somekey: 'someValB', section: ['valueY', 'valueX', 'valueZ']},
{id: 4, somekey: 'someValA', section: []}
];
//Nested Example
//const nestedGrouped = groupBy(inputNested, ["somekey", "section"]);
//console.log(nestedGrouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Упрощенный код для вашей конкретной проблемы c 1-го уровня:
const input = [
{id: 0, section: ['valueX']},
{id: 1, section: ['valueX']},
{id: 2, section: ['valueY']},
{id: 3, section: ['valueY', 'valueX', 'valueZ']},
{id: 4, section: []}
];
const groupBy = (input, propertyArr) => {
//console.log(propertyArr);
const property = propertyArr[0];
const grouped = input.reduce((groupedObj, item) => {
const key = item[property];
if (key instanceof Array && key.length > 0){
key.forEach(k => {
groupedObj[k] = [...(groupedObj[k] || []), item];
})
}else{
groupedObj['all'] = [...(groupedObj['all'] || []), item];
}
return groupedObj;
}, {});
return grouped;
};
const nestedGrouped = groupBy(input, ["section"]);
console.log(nestedGrouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Вот ваш код для справки:
const input = [
{id: 0, section: ['valueX']},
{id: 1, section: ['valueX']},
{id: 2, section: ['valueY']},
{id: 3, section: ['valueY', 'valueX', 'valueZ']},
{id: 4, section: []}
];
const groupBy = ({ data, property }) =>
data.reduce((arr, current) => {
const result = arr;
const groupList = current[property];
const groupHasItems = groupList.length > 0;
const groupItemExists = result[groupList];
if (groupHasItems && !groupItemExists) {
groupList.forEach(id => {
if (!result[id]) {
result[id] = [];
}
});
} else if (!result.all) {
result.all = [];
}
if (groupHasItems) {
groupList.forEach(id => {
result[id].push(current);
});
} else {
result.all.push(current);
}
return result;
}, {});
console.log(groupBy({ data: input, property: 'section'}))
.as-console-wrapper { max-height: 100% !important; top: 0; }