繁体   English   中英

Ramda - 通过多个分组变换数组

[英]Ramda - Transform array by multiple groupings

我正在尝试使用ramda完成以下操作:

这是array的外观示例:

[
  {
    id: 1,
    value: "ON",
    type: "TYPE_1"
  },
  {
    id: 1,
    value: "OFF",
    type: "TYPE_1"
  },
  {
    id: 2,
    value: "ON",
    type: "TYPE_1"
  }, {
    id: 3,
    value: "OFF",
    type: "TYPE_2"
  },
  {
    id: 3,
    value: "OFF",
    type: "TYPE_2"
  },
  {
    id: 3,
    value: "OFF",
    type: "TYPE_2"
  }
]

这是我希望它的外观:

[
 {
  name: "TYPE_1"
  enabled: 2,
  disabled: 0,
 },
 {
  name: "TYPE_2",
  enabled: 0,
  disabled: 1
 }
]

基本上我需要按typeid分组,它们的组合可以重复但只占一个。

这是我已经尝试过的:

pipe(
  groupBy(prop('type')),
  map(applySpec({
    name: pipe(head, prop('type')),
    enabled: reduce((acc, item) => item.value === "ON" ? add(acc, 1) : acc, 0),
    disabled: reduce((acc, item) => item.value === "OFF" ? add(acc, 1) : acc, 0) 
  })),
  values,
)(list) 

但它不起作用,因为它返回以下内容:

[
 {
  name: "TYPE_1",
  enabled: 2,
  disabled: 1
 },
 {
  type: "TYPE_2",
  enabled: 0,
  disabled: 3
]

缺少的部分是只考虑每种type的每个id

您需要按id再次分组,从每个子组中取出头部,展平,然后应用规范:

 const { pipe, groupBy, prop, values, map, applySpec, head, ifElse, any, always, filter, propEq, length } = R const fn = pipe( groupBy(prop('type')), values, map(pipe( groupBy(prop('id')), values, map(applySpec({ name: pipe(head, prop('type')), value: ifElse(any(propEq('value', 'ON')), always('ON'), always('OFF')), })), applySpec({ name: pipe(head, prop('name')), enabled: pipe(filter(propEq('value', 'ON')), length), disabled: pipe(filter(propEq('value', 'OFF')), length), }) )), ) const arr = [{"id":1,"value":"ON","type":"TYPE_1"},{"id":1,"value":"OFF","type":"TYPE_1"},{"id":2,"value":"ON","type":"TYPE_1"},{"id":3,"value":"OFF","type":"TYPE_2"},{"id":3,"value":"OFF","type":"TYPE_2"},{"id":3,"value":"OFF","type":"TYPE_2"}] const result = fn(arr) console.log(result)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

尝试这个:

const transform = applySpec({
  name: head,
  enabled: pipe(last, filter(propEq('value', 'ON')), length),
  disabled: pipe(last, filter(propEq('value', 'OFF')), length),
})
const fn = pipe(groupBy(prop('type')), toPairs, map(transform))

演示

这是另一种方法,与 OriDrori 的方法有些不同。 它与给定的情况相匹配,但我仍然不确定一般规则,因此这可能实际上并没有正确捕获需求。

 const extract = pipe ( groupBy (toString), // {JSON_key1: [{id, value, type}, {id, value, type}, ...] JSON_key2: [{id, value, type}, ...], ...} map (head), // {JSON_key1: {id, value, type}, JSON_key2: {id, value, type}, ...} values, // [{id, value, type}, {id, value, type}, ...] groupBy (prop ('type')), // {TYPE_1: [{id, value, type}, {id, value, type}, ...], "TYPE_2":[{id, value, type}]} map (countBy (prop ('value'))), // {TYPE_1: {ON: 2, OFF: 1}, TYPE_2: {OFF: 1}} toPairs, // [[TYPE_1, {ON: 2, OFF: 1}], [TYPE_2, {OFF: 1}]] map (applySpec ({ type: nth(0), enabled: pathOr(0, [1, 'ON']), disabled: pathOr(0, [1, 'OFF']) })) // [{type: "TYPE_1", enabled: 2, disabled: 1}, {type: "TYPE_2", enabled: 0, disabled: 1}] ) const data = [{id: 1, value: "ON", type: "TYPE_1"}, {id: 1, value: "OFF", type: "TYPE_1"}, {id: 2, value: "ON", type: "TYPE_1"}, {id: 3, value: "OFF", type: "TYPE_2"}, {id: 3, value: "OFF", type: "TYPE_2"}, {id: 3, value: "OFF", type: "TYPE_2"}]; console.log (extract (data))
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script> <script> const {pipe, groupBy, toString, map, head, values, prop, countBy, toPairs, applySpec, nth, pathOr} = R </script>

Ramda 的toString并不是特别快。 如果您愿意,可以将管道的第一行替换为以下内容:

  groupBy (({id, value, type}) => `${id}|${value}|${type}`),

此外, map(applySpec)行感觉有点复杂。 我们可以用这样的东西替换它们:

  map (([type, {OFF: disabled = 0, ON: enabled = 0}]) => ({type, enabled, disabled}))

请注意小型、相对简单的单个转换管道的样式。 这对我来说是 Ramda 的最佳选择。 Ramda 旨在支持许多不同的 styles 函数式编程,但这种风格是最核心的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM