我有一个问题,要把下面的数组data1转换为data2的样子:我试着用lodash,但有点奇怪,_gropuby给我一个对象数组。我应该在数组中循环......创建一个自定义函数,还是在lodash中有一个技巧来简化这个问题。
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"
}
]
//The output should be like a tree array system, something more organized such as the following code :
let data2 = [{
KlasCode: "AA",
Modules: [
{
ModuleID: "1061",
Participation: [{
ParticipationLetterCode: "Y",
LESDatum: "06/02/2017",
LESID: "1"
},
{
ParticipationLetterCode: "X",
LESDatum: "07/02/2017",
LESID: "2"
}
},
{
ModuleID: "1062",
Participation:[{
ParticipationLetterCode: "Z",
LESDatum: "13/02/2017",
LESID: "3"
}]
}
}]
},
{
KlasCode: "BB",
Modules: [{
ModuleID: "1063",
Participation: [{
ParticipationLetterCode: "x",
LESDatum: "6/02/2017",
LESID: "4"
}]
}]
}
]
创建了一个函数来做同样的事情,希望对你有帮助-。
const custommodifier = (data) => Object.values(data.reduce((acc,{KlasCode, ModuleID, ...participationData}) => {
if(acc[KlasCode]){
acc[KlasCode].Modules[0].Participation.push({
...participationData
})
}
else {
acc[KlasCode] = {
KlasCode,
Modules: [{
ModuleID,
Participation: [{
...participationData
}]
}]
}
}
return acc;
}, {}));
let data = [{
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: "1061",
ParticipationLetterCode: "Z"
},
{
KlasCode: "BB",
LESDatum: "16/02/2017",
LESID: "4",
ModuleID: "1062",
ParticipationLetterCode: "X"
}
]
console.log(custommodifier(data))
你可以用一个动态的方法,用一个键和组名的数组,然后从实际的对象中取出键。最后,在建立嵌套组后,将最终对象添加到最后一个组中。
如果有必要,这种方法适用于更多的嵌套组。
let data = [{ 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: "1061", ParticipationLetterCode: "Z" }, { KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1062", ParticipationLetterCode: "X" }],
groups = [['KlasCode', 'Modules'], ['ModuleID', 'Participation']],
result = data.reduce((r, o) => {
groups
.reduce((p, [key, group]) => {
let value, temp;
({ [key]: value, ...o } = o);
temp = p.find(q => q[key] === value);
if (!temp) p.push(temp = { [key]: value, [group]: [] });
return temp[group];
}, r)
.push(o);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我会使用一个 groupBy
函数,再配合使用一下 Object.entries
. 你将需要使用它两次,以处理你的两个级别的分组。
你可以使用 groupBy
从lodash(或Ramda,或任何地方),或这里的简单的一个。
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函数移植到vanilla JS中。 这次我不打算做后者,但我会分享如何利用Ramda这样的库来做这件事。 我猜测lodash中也有类似的功能。
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>
我感觉这些功能更简单,更能显示出转换的步骤。 但这还不足以成为包含一个库的理由。 但是一旦你有了一些这样的情况,一个库似乎就很有意义了。
我在这里并不是想推崇Ramda,只是想指出,当你有实用库的工具可以使用时,你往往可以写出更简单的代码。