我们可以在此基础上构建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))}
: {}
)
然而,这给我们的函数带来了一些丑陋。