繁体   English   中英

使用 Ramda 减少对象数组中的多个属性并省略其他属性

[英]Reduce multiple properties in array of array of objects and omit other properties using Ramda

我有这个带有对象的 arrays 数组:

const data = [
  [
    {
      index: 320,
      blocks: 2,
      value: '31011784785',
      participants: 1222,
      cost: '1286828506'
    },
    {
      index: 319,
      blocks: 0,
      value: '111306385',
      participants: 18,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '14550473',
      participants: 10,
      cost: '0'
    }
  ],
  [
    {
      index: 320,
      blocks: 1,
      value: '7089001673',
      participants: 492,
      cost: '648196615'
    },
    {
      index: 319,
      blocks: 0,
      value: '13551137',
      participants: 8,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '11499815',
      participants: 5,
      cost: '0'
    }
  ],
  [
    {
      index: 320,
      blocks: 1,
      value: '408900161',
      participants: 200,
      cost: '648196615'
    },
    {
      index: 319,
      blocks: 0,
      value: '23551231',
      participants: 10,
      cost: '0'
    },
    {
      index: 318,
      blocks: 0,
      value: '104324219',
      participants: 5,
      cost: '0'
    }
  ]
]

我想制作一个包含对象的单个数组,这些对象将仅具有属性索引、值和参与者,其中值和参与者将是 3 arrays 的总和。例如:

[
  {
      index: 320,
      value: 38509686619,
      participants: 1914,
  },
  {
      index: 319,
      value: 148408753,
      participants: 36,
  },
  {
     ...
  }
]

我还希望值字段是一个 BigInt。

受这个答案的启发,我做了一些有用的东西,但它太长太麻烦了。

这个问题与使用 Ramda 减少对象数组的问题不同,因为我需要两个 object 属性值,但我不知道该怎么做。

香草 JS 解决方案:

 const data = [[{"index":320,"blocks":2,"value":"31011784785","participants":1222,"cost":"1286828506"},{"index":319,"blocks":0,"value":"111306385","participants":18,"cost":"0"},{"index":318,"blocks":0,"value":"14550473","participants":10,"cost":"0"}],[{"index":320,"blocks":1,"value":"7089001673","participants":492,"cost":"648196615"},{"index":319,"blocks":0,"value":"13551137","participants":8,"cost":"0"},{"index":318,"blocks":0,"value":"11499815","participants":5,"cost":"0"}],[{"index":320,"blocks":1,"value":"408900161","participants":200,"cost":"648196615"},{"index":319,"blocks":0,"value":"23551231","participants":10,"cost":"0"},{"index":318,"blocks":0,"value":"104324219","participants":5,"cost":"0"}]]; const result = Object.values(data.flat().reduce((acc, { index, value, participants }) => { acc[index]??= { index, value: 0, participants: 0 }; acc[index].value += Number(value); acc[index].participants += Number(participants); return acc; }, {})); console.log(result);
 .as-console-wrapper{min-height: 100%;important: top: 0}

一种 Ramda 方法:

 const convert = pipe ( transpose, map (xs => ({ index: xs [0].index, value: xs.reduce ((a, {value}) => a + Number (value), 0), participants: sum (pluck ('participants') (xs)) })) ) const data = [[{index: 320, blocks: 2, value: "31011784785", participants: 1222, cost: "1286828506"}, {index: 319, blocks: 0, value: "111306385", participants: 18, cost: "0"}, {index: 318, blocks: 0, value: "14550473", participants: 10, cost: "0"}], [{index: 320, blocks: 1, value: "7089001673", participants: 492, cost: "648196615"}, {index: 319, blocks: 0, value: "13551137", participants: 8, cost: "0"}, {index: 318, blocks: 0, value: "11499815", participants: 5, cost: "0"}], [{index: 320, blocks: 1, value: "408900161", participants: 200, cost: "648196615"}, {index: 319, blocks: 0, value: "23551231", participants: 10, cost: "0"}, {index: 318, blocks: 0, value: "104324219", participants: 5, cost: "0"}]] console.log (convert (data))
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script> <script> const {pipe, transpose, map, sum, pluck, reduce, applySpec} = R </script>

我们从transpose开始,它将它变成一种更容易使用的格式。 然后对于每个新行,我们从第一条记录中获取索引,并对参与者和值求和。

因为 BigInt 在 SO 控制台中显示不佳,所以我跳过了它们,但变化很小:

-    value: xs .reduce ((a, {value}) => a + Number (value), 0),
+    value: xs .reduce ((a, {value}) => a + BigInt(value), BigInt(0)),

一个无积分版本,如果你有那种迷信,也不会更难:

const convert = pipe (
  transpose,
  map (applySpec ({
    index: pipe (head, prop ('index')),
    value: reduce ((a, {value}) => a + Number (value), 0),
    // value: reduce ((a, {value}) => a + BigInt (value), BigInt (0)),
    participants: pipe (pluck ('participants'), sum)
  }))
)

扁平化后,arrays 的数组,你应该 map 并选择想要的属性并将values转换为数字,然后分组,并将每个组组合成一个 object。

 const { mergeWithKey, pipe, flatten, map, pick, evolve, groupBy, prop, reduce, values } = R // merge deep and combine properties value const combine = mergeWithKey((k, l, r) => k === 'value' || k === 'participants'? l + r: r) const mergeData = pipe( flatten, // flatten to a single array map(pipe( pick(['index', 'value', 'participants']), // pick wanted properties evolve({ value: Number }) // convert values to a number )), groupBy(prop('index')), // group by the name map(reduce(combine, {})), // combine each group to a single object values, // convert back to array ) const data = [[{"index":320,"blocks":2,"value":"31011784785","participants":1222,"cost":"1286828506"},{"index":319,"blocks":0,"value":"111306385","participants":18,"cost":"0"},{"index":318,"blocks":0,"value":"14550473","participants":10,"cost":"0"}],[{"index":320,"blocks":1,"value":"7089001673","participants":492,"cost":"648196615"},{"index":319,"blocks":0,"value":"13551137","participants":8,"cost":"0"},{"index":318,"blocks":0,"value":"11499815","participants":5,"cost":"0"}],[{"index":320,"blocks":1,"value":"408900161","participants":200,"cost":"648196615"},{"index":319,"blocks":0,"value":"23551231","participants":10,"cost":"0"},{"index":318,"blocks":0,"value":"104324219","participants":5,"cost":"0"}]] const results = mergeData(data) console.log(results)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

此解决方案(使用 JS 而不是 rambda)尝试使用 BigInt 并将值提供给名为valueB的道具。

 const groupAndSum = arr => ( Object.values( arr.flat().reduce( (acc, {index, value, participants}) => ({...acc, [index]: { index, valueB: BigInt((acc[index]?.valueB?? 0)) + BigInt(value), // valueB as big-int value: (acc[index]?.value || 0) + +value, // value as a "Number" participants: (acc[index]?.participants?? 0) + +participants } }), {} ) ).map( // to display big-int in the console within stack-snippets ({valueB, ...rest}) => ({valueB: valueB.toString(), ...rest}) ) ); const data = [ [ { index: 320, blocks: 2, value: '31011784785', participants: 1222, cost: '1286828506' }, { index: 319, blocks: 0, value: '111306385', participants: 18, cost: '0' }, { index: 318, blocks: 0, value: '14550473', participants: 10, cost: '0' } ], [ { index: 320, blocks: 1, value: '7089001673', participants: 492, cost: '648196615' }, { index: 319, blocks: 0, value: '13551137', participants: 8, cost: '0' }, { index: 318, blocks: 0, value: '11499815', participants: 5, cost: '0' } ], [ { index: 320, blocks: 1, value: '408900161', participants: 200, cost: '648196615' }, { index: 319, blocks: 0, value: '23551231', participants: 10, cost: '0' }, { index: 318, blocks: 0, value: '104324219', participants: 5, cost: '0' } ] ]; console.log(groupAndSum(data));

解释

  • Object.values()用于从以下操作中提取结果对象的值
  • 首先,将输入数组展flat以去除嵌套
  • 接下来, .reduce用于遍历数组并生成结果对象
  • acc是累加器/聚合器 object
  • 每个index要么作为新键添加到acc中,其值为实际 object
  • 如果index已经存在于acc中,那么将对valueparticipants道具求和。
  • valueB是一个新的 prop 来存储BigInt格式的value

附加的.map()用于使valueB可在堆栈片段的console.log中显示。 这在原始代码中可能不需要 - 所以请忽略。

暂无
暂无

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

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