У меня есть небольшое веб-приложение, которое извлекает данные с помощью вызова API, ответ представляет собой массив отчетов, каждый отчет имеет уникальный идентификатор, приложение, тип и заголовок.
Я хочу сопоставить его с новым объектом, сгруппировав его по приложению, а затем по типам. как описано ниже.
[
{
"id": "REPORT1",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT2",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT3",
"application": "APP1",
"type": "TYPE2",
"title": ""
},
{
"id": "REPORT4",
"application": "APP2",
"type": "TYPE3",
"title": ""
}
]
{
"APP1": {
"TYPE1": [
{
"id": "REPORT1",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT2",
"application": "APP1",
"type": "TYPE1",
"title": ""
}
],
"TYPE2": [
{
"id": "REPORT3",
"application": "APP1",
"type": "TYPE2",
"title": ""
}
]
},
"APP2": {
"TYPE3": [
{
"id": "REPORT4",
"application": "APP2",
"type": "TYPE3",
"title": ""
}
]
}
}
С loadash я придумал следующее:
const output = _(input)
.groupBy(report => report.application)
.value()
После группы по application мне нужно сделать еще одну вложенную группировку или сопоставление по type, но застрял.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это может быть легко реализовано без lodash через функция Array#reduce().
Подробнее о том, как это достигается, см. Комментарии в исходном коде фрагментов кода:
var input = [{
"id": "REPORT1",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT2",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT3",
"application": "APP1",
"type": "TYPE2",
"title": ""
},
{
"id": "REPORT4",
"application": "APP2",
"type": "TYPE3",
"title": ""
}
];
var output = input.reduce((result, item) => {
// Get app object corresponding to current item from result (or insert if not present)
var app = result[item.application] = result[item.application] || {};
// Get type array corresponding to current item from app object (or insert if not present)
var type = app[item.type] = app[item.type] || [];
// Add current item to current type array
type.push(item);
// Return the result object for this iteration
return result;
}, {});
console.info(output);.as-console-wrapper {
height:100% !important;
max-height:unset !important;
}Спасибо за упоминание о сокращении ……
Добро пожаловать, @HossamMaher
Вы можете применить динамический подход с желаемыми ключами для группировки.
groups = ["application", "type"]
Затем уменьшите массив данных и массив ключей и создайте либо новые объекты, если необходимо, либо с последней группой массив для проталкивания фактического объекта.
При необходимости это решение может быть легко расширено на большее количество вложенных групп.
var data = [{ id: "REPORT1", application: "APP1", type: "TYPE1", title: "" }, { id: "REPORT2", application: "APP1", type: "TYPE1", title: "" }, { id: "REPORT3", application: "APP1", type: "TYPE2", title: "" }, { id: "REPORT4", application: "APP2", type: "TYPE3", title: "" }],
groups = ["application", "type"],
grouped = data.reduce((r, o) => {
groups
.reduce((group, key, i, { length }) =>
group[o[key]] = group[o[key]] || (i + 1 === length ? [] : {}), r)
.push(o);
return r;
}, {});
console.info(grouped);.as-console-wrapper { max-height: 100% !important; top: 0; }es6, распространение и уменьшение объектов делают его проще
const input = [
{
"id": "REPORT1",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT2",
"application": "APP1",
"type": "TYPE1",
"title": ""
},
{
"id": "REPORT3",
"application": "APP1",
"type": "TYPE2",
"title": ""
},
{
"id": "REPORT4",
"application": "APP2",
"type": "TYPE3",
"title": ""
}
]
const output = input.reduce((acc, item) => ({
...acc,
[item.application]: {
...acc[item.application],
[item.type]: [
...(acc[item.application] && acc[item.application][item.type] || []),
item,
]
}
}), {})
console.info(output)Я лично нашел это более читаемым при объединении _.groupBy и _.mapValues в Lodash:
var input = [{ id: "REPORT1", application: "APP1", type: "TYPE1", title: "" }, { id: "REPORT2", application: "APP1", type: "TYPE1", title: "" }, { id: "REPORT3", application: "APP1", type: "TYPE2", title: "" }, { id: "REPORT4", application: "APP2", type: "TYPE3", title: "" }]
const output = _.mapValues(_.groupBy(input, i => i.application),app => _.groupBy(app, i => i.type))
console.info(output)<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
Хорошая работа без нагрузки :)