RamdaJS转换对象并使用其他列表进行查找

问题描述 投票:0回答:2

继续从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)

预期输出是类属性附加到嵌套的kids数组。

{
    "father": "Jack",
    "count" : 1,
    "kids": [
      { "name": "Jeff", "age": 11, "class" : "11-C" }
    ]
  }
ramda.js
2个回答
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/[email protected]"></script><script>
const {defaultTo, find, propEq, pipe, groupBy, map, applySpec, head, prop, length, dissoc, values} = ramda
</script>

请注意,如果孩子的名字不在school中,则为schoolList提供默认值。


1
投票

使用schoolListR.indexBy转换为名称对象的字典。使用翻转的道具从查找中创建pickFromLookupByName。使用pick提取你想要的道具。

要将class添加到kid对象,请使用带有R.converge的kid对象的R.identity,并使用pickClass获取包含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)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.