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

时间:2019-04-05 02:03:54

标签: ramda.js

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" }
    ]
  }

2 个答案:

答案 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)

使用schoolListR.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)