从RamdaJS groupBy and tranform object继续
let children = [
{ "name": "Bob", "age": 8, "father": "Mike" },
{ "name": "David", "age": 10, "father": "Mike" },
{ "name": "Amy", "age": 2, "father": "Mike" },
{ "name": "Jeff", "age": 11, "father": "Jack" }
]
let schoolList = [
{ "name": "Bob", "class": "8-A", "school": "School 1" },
{ "name": "David", "class": "10-B", "school": "School 1" },
{ "name": "Amy", "class": "2-A", "school": "School 1" },
{ "name": "Jeff", "class": "11-C", "school": "School 1" }
]
到目前为止我做了什么。
R.pipe(
R.groupBy(R.prop('father')),
R.map(R.applySpec({
father: R.pipe(R.head, R.prop('father')),
count: R.length,
kids: R.map(R.dissoc('father')),
class: R.map(R.prop('class'))R.find(R.propEq('name',R.pipe(R.head, R.prop('name'))), schoolList)
})),
R.values()
)(children)
预期的输出是 class 属性被附加到嵌套的孩子数组。
{
"father": "Jack",
"count" : 1,
"kids": [
{ "name": "Jeff", "age": 11, "class" : "11-C" }
]
}
答案 0 :(得分:1)
如果实际的schoolList
很长,我会使用OriDrori的答案。但是,如果它很短,那么即使效率较低,它也可能会更干净一些:
const expandChild = schoolList => child => ({
...child,
class: defaultTo(
{class: 'unknown'},
find(propEq('name', child.name), schoolList)
).class
})
const groupChildren = schoolList => pipe(
groupBy(prop('father')),
map(applySpec({
father: pipe(head, prop('father')),
count: length,
kids: map(pipe(dissoc('father'), expandChild(schoolList)))
})),
values,
)
let children = [{ name: "Bob", age: 8, father: "Mike" }, { name: "David", age: 10, father: "Mike" }, { name: "Amy", age: 2, father: "Mike" }, { name: "Jeff", age: 11, father: "Jack" }, { name: "Sue", age: 9, father: "Jack" }]
let schoolList = [{ name: "Bob", class: "8-A", school: "School 1" }, { name: "David", class: "10-B", school: "School 1" }, { name: "Amy", class: "2-A", school: "School 1" }, { name: "Jeff", class: "11-C", school: "School 1" }]
console.log (groupChildren (schoolList) (children))
<script src="https://bundle.run/ramda@0.26.1"></script><script>
const {defaultTo, find, propEq, pipe, groupBy, map, applySpec, head, prop, length, dissoc, values} = ramda
</script>
请注意,如果孩子的名字不在school
中,则为schoolList
提供默认值。
答案 1 :(得分:0)
使用schoolList
将R.indexBy
转换为对象字典。通过使用翻转的道具从查找中创建pickFromLookupByName
。使用pick
提取所需的道具。
要向孩子对象添加class
,请使用R.converge
,该对象将孩子对象与R.identity
一起使用,并使用pickClass
获取包含{{1 }},并与class
合并。
R.mergeRight
const { pipe, groupBy, prop, applySpec, head, length, map, dissoc, values, indexBy, converge, mergeRight, flip, pick, identity } = R
const schoolList = [{"name":"Bob","class":"8-A","school":"School 1"},{"name":"David","class":"10-B","school":"School 1"},{"name":"Amy","class":"2-A","school":"School 1"},{"name":"Jeff","class":"11-C","school":"School 1"}]
const schoolLookup = indexBy(prop('name'), schoolList);
const pickFromLookupByName = (propList) => pipe(
flip(prop)(schoolLookup),
pick(propList),
)
const pickClass = pickFromLookupByName(['class']) // convenience method to get an object containing the class
const fn = pipe(
groupBy(prop('father')),
map(applySpec({
father: pipe(head, prop('father')),
count: length,
kids: map(pipe(
dissoc('father'),
converge(mergeRight, [identity, pipe(prop('name'), pickClass)])
))
})),
values
)
const children = [{"name":"Bob","age":8,"father":"Mike"},{"name":"David","age":10,"father":"Mike"},{"name":"Amy","age":2,"father":"Mike"},{"name":"Jeff","age":11,"father":"Jack"}]
const result = fn(children)
console.log(result)