在 javascript 中对对象数组应用 group by 和 sum

2023-12-22

我需要一些关于实现对 JSON 数据应用 group by 和 sum 的目标的正确方法的建议。

一些服务器端代码实际上生成了我必须使用的 JSON:

[
    {
        "siteDetails": {
            "printerCode": "660103684",
            "siteId": "UTT212303-STB-2040-0003"
        },
        "printingMaterialCode": "400000033",
        "printingQuantity": 400,
        "approved": true
    },
    {
        "siteDetails": {
            "printerCode": "660103684",
            "siteId": "UTT212303-STB-2040-0002"
        },
        "printingMaterialCode": "400000033",
        "printingQuantity": 600,
        "campaignId": "DATAS00002",
    },
    {
        "siteDetails": {
            "printerCode": "660103684",
            "siteId": "UTT212303-STB-2040-0001"
        },
        "printingMaterialCode": "400000034",
        "printingQuantity": 300,
        "campaignId": "DATAS00002",
    }
]

现在,我需要应用一些操作(可能是 groupby 和 sum)来获得以下结果:

[
    {
        "printingMaterialCode": "400000033",
        "printingQuantity": 1000
        "approvedQuantity": 400
    },
    {
        "printingMaterialCode": "400000034",
        "printingQuantity": 300,
    }
]

基本上,输出是printingQuantity和approvedQuantitySUM根据印刷材料代码。


我们可以在此基础上构建reduce以相当简单的方式,像这样:

const combine = (xs) => Object .entries (xs .reduce (
  (a, {printingMaterialCode, printingQuantity, approved = false}) => {
    const pmc = a [printingMaterialCode] || {printingQuantity: 0}
    pmc .printingQuantity += printingQuantity
    if (approved) pmc .approvedQuantity = (pmc .approvedQuantity || 0) + printingQuantity
    a [printingMaterialCode] = pmc
    return a
  },
  {}
)) .map (([printingMaterialCode, rest]) => ({printingMaterialCode, ...rest}))

const input = [{siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0003"}, printingMaterialCode: "400000033", printingQuantity: 400, approved: !0}, {siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0002"}, printingMaterialCode: "400000033", printingQuantity: 600, campaignId: "DATAS00002"}, {siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0001"}, printingMaterialCode: "400000034", printingQuantity: 300, campaignId: "DATAS00002"}]

console .log (combine (input))

但我认为使用一些通用辅助函数来处理分组和求和并使您的代码更具体地满足您的要求会更干净,如下所示:

const group = (fn) => (xs) => Object .values (
  xs .reduce ((a, x, _, __, k = fn (x)) => ((a [k] = [... a [k] || [], x]), a), {})
)

const sum = (ns) => ns .reduce ((a, b) => a + b, 0)

const combine = (xs) => 
  group (x => x.printingMaterialCode) (xs)
    .map ((xs) => ({
      printingMaterialCode : xs [0] .printingMaterialCode, 
      printingQuantity: sum (xs .map (x => x .printingQuantity)),
      approvedQuantity: sum (xs .filter (x => x.approved) .map (x => x .printingQuantity))
    }))

const input = [{siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0003"}, printingMaterialCode: "400000033", printingQuantity: 400, approved: !0}, {siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0002"}, printingMaterialCode: "400000033", printingQuantity: 600, campaignId: "DATAS00002"}, {siteDetails: {printerCode: "660103684", siteId: "UTT212303-STB-2040-0001"}, printingMaterialCode: "400000034", printingQuantity: 300, campaignId: "DATAS00002"}]

console .log (combine (input))

Here, group接受一个键提取函数并返回一个函数,该函数接受一个值数组并返回映射到同一键的元素的数组数组。例如,要按最后一位数字对数字数组进行分组,我们可以这样做:

group (n => n % 10) ([1, 12, 3, 52, 11, 56, 13, 32])
  //=> [[1, 11], [12, 52, 32], [3, 13], [56]]

如果您使用的库具有groupBy函数,那么你可以用类似的东西替换它

const group = (fn) => (xs) => Object .values (groupBy (fn, xs))
                                      // or   groupBy (xs, fn))
                                      // or   groupBy (fn) (xs))
                                      // based on `groupBy`'s sig

sum当然,只是对一组数字求和。

So combine然后将数字分组printingMaterialCode值,那么map是具有您请求的属性的对象的结果。

这与您请求的结构有一个区别,那就是没有的组approved条目,仍然有一个approvedQuantity场地;它只是设置为零。我个人更喜欢这种行为,因为一致的数据总是胜利。但如果你想改变这一点,你可以替换这一行:

      approvedQuantity: sum (xs .filter (x => x.approved) .map (x => x .printingQuantity))

有了这个:

      ... (xs .some (x => x.approved) 
        ? {approvedQuantity: sum (xs .filter (x => x.approved) .map (x => x .printingQuantity))} 
        : {}
      )

然而,这给我们的函数带来了一些丑陋。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 javascript 中对对象数组应用 group by 和 sum 的相关文章

随机推荐