Я бы использовал функцию groupBy
в сочетании с небольшим переключением с Object.entries
. Вам нужно будет использовать его дважды, чтобы справиться с вашими двумя уровнями группировки.
Вы можете использовать groupBy
от loda sh (или тот, что от Рамды, или где угодно), или простой включенный здесь.
const groupBy = (fn) => (xs) =>
xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})
const transform = (data) => Object.entries (groupBy (x => x.KlasCode) (data))
.map(([KlasCode, Modules]) => ({
KlasCode,
Modules: Object.entries(groupBy (x => x.ModuleID) (Modules))
.map(([ModuleID, Participations]) => ({
ModuleID,
Participation: Participations.map (({ParticipationLetterCode, KlasCode, ...rest}) => rest)
})
)
}))
let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]
console .log (transform (data1))
.as-console-wrapper {min-height: 100% !important; top: 0}
Обновление - альтернатива Ramda
Меня не поразило ни вышеупомянутое решение, ни другие ответы здесь. Иногда, когда это происходит, я переписываю в Ramda (отказ от ответственности: я один из его авторов), а затем портирую функции Ramda, включенные в vanilla JS. Я не собираюсь делать последнее на этот раз, но я поделюсь, как я мог бы сделать это, используя в своих интересах библиотеку как Рамда. Я предполагаю, что в loda sh.
есть похожие функции.
const groupByProp = (propName, childName) => pipe (
groupBy (prop (propName)),
toPairs,
map (evolve ([ , map (dissoc (propName))])),
map (zipObj ([propName, childName]))
)
const transform = pipe (
groupByProp('KlasCode', 'Modules'),
map (evolve ({Modules: groupByProp('ModuleID', 'Participation')}))
)
let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]
console .log (transform (data1))
.as-console-wrapper {min-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {groupBy, prop, toPairs, map, evolve, dissoc, zipObj, pipe} = R </script>
Мне кажется, что эти функции проще и лучше показывают этапы преобразования. Но этого недостаточно для включения библиотеки. Но если у вас есть несколько таких ситуаций, библиотека, кажется, имеет большой смысл.
Я не пытаюсь описать Рамду здесь, просто чтобы указать, что когда у вас есть инструменты утилита библиотека в вашем распоряжении, вы часто можете написать более простой код.