使用 Ramda 对数组的项目进行分组和转换

Using Ramda to group and transform items of an array

我需要按 batchNumber 对数组中的项目进行分组,然后对它们的值求和。

目前我正在使用ramda,但我可以分组但不能转换结果。

能否请您提供一个使用 ramda.js 的示例?

Live Example:

const input = [
    {
        batchNumber: 'a',
        scrapAmount: 5
    },
    {
        batchNumber: 'a',
        scrapAmount: 10
    },
    {
        batchNumber: 'b',
        scrapAmount: 1
    },
    {
        batchNumber: 'b',
        scrapAmount: 2
    },
    {
        scrapAmount: 7
    },
    {
        scrapAmount: 3
    }
]

const byBatchNumber = R.groupBy((batch) => batch.batchNumber);


console.log(byBatchNumber(input))

/* result wanted

const output = [
    {
        batchNumber: 'a',
        scrapAmount: 15
    },
    {
        batchNumber: 'b',
        scrapAmount: 3
    },
    {
        batchNumber: undefined,
        scrapAmount: 10
    },
]

*/

groupWith() by checking that the batchNumber is equal with eqProps(). Then map() each subarray, apply mergeWithKey() to all objects, and add() scrapAmount 字段的值:

const { compose, groupWith, eqProps, map, apply, mergeWithKey, add } = R;

const input = [{"batchNumber":"a","scrapAmount":5},{"batchNumber":"a","scrapAmount":10},{"batchNumber":"b","scrapAmount":1},{"batchNumber":"b","scrapAmount":2},{"scrapAmount":7},{"scrapAmount":3}]

const byBatchNumber = compose(
  map(apply(mergeWithKey((k, l, r) => k === 'scrapAmount' ? add(l, r) : r))),
  groupWith(eqProps('batchNumber'))
)

console.log(byBatchNumber(input))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

一个相当简单的版本如下:

const {pipe, groupBy, prop, map, pluck, sum} = R;

const input = [
    {batchNumber: 'a', scrapAmount: 5},
    {batchNumber: 'a', scrapAmount: 10},
    {batchNumber: 'b', scrapAmount: 1},
    {batchNumber: 'b', scrapAmount: 2},
    {scrapAmount: 7},
    {scrapAmount: 3}
]

const totalScrap = pipe(
  groupBy(prop('batchNumber')), 
  map(pluck('scrapAmount')), 
  map(sum)
)

console.log(totalScrap(input))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

首先请注意,这将 R.groupBy((batch) => batch.batchNumber) 简化为 R.groupBy(R.prop('batchNumber'));功能一样,只是表述更简洁。

这是我所能做的,因为我相信这是对我通常做的工作最有用的输出格式,即像这样的东西:

{"a": 15, "b": 3, "undefined": 10}

但是重新读取您需要的输出,可能还需要两个步骤:

const {pipe, groupBy, prop, map, pluck, sum, toPairs, zipObj} = R;

const input = [
    {batchNumber: 'a', scrapAmount: 5},
    {batchNumber: 'a', scrapAmount: 10},
    {batchNumber: 'b', scrapAmount: 1},
    {batchNumber: 'b', scrapAmount: 2},
    {scrapAmount: 7},
    {scrapAmount: 3}
]

const totalScrap = pipe(
  groupBy(prop('batchNumber')), 
  map(pluck('scrapAmount')), 
  map(sum),
  toPairs,
  map(zipObj(['batchNumber', 'scrapAmount']))
)

console.log(totalScrap(input))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

这不会做的一件事是生成一个带有 batchNumber: undefined 的项目,而不是 returns 一个带有 batchNumber: "undefined"(字符串)的项目。虽然这可以修复,但它一个丑陋的步骤,我看不到真正的收获。如果您有一个值为 "undefined" 的解决方案,则可能会失败。如果这真的是一个阻碍,你显然可以在该管道的最后一步之前处理这些。