【问题标题】:Javascript ES6 calculate the sum of an array of arrays of objectsJavascript ES6计算对象数组的总和
【发布时间】:2019-07-22 19:08:40
【问题描述】:

我有多个具有字符串属性"CountType" 和数字属性"ItemCount" 的对象数组。

对象必须相加才能通过"CountType"属性计算所有项目的总和。

例如,我需要知道 Volumes、Sheets、Photos 等的总数。

尝试 #1:我尝试的这段代码返回 0。这可能是因为我需要遍历外部数组来对嵌套数组进行比较。

function sumByProperty(items, prop) {
  if (items == null) {
      return 0;
  }
  return items.reduce(function (a, b) {
      return b[prop] == null ? a : a + b[prop];
  }, 0);
}

输入

商品数量

[
    [
      {"CountType":"Volumes","ItemCount":3},
      {"CountType":"Sheets","ItemCount":6},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":1},
      {"CountType":"Other","ItemCount":2}
    ],
    [
      {"CountType":"Volumes","ItemCount":1},
      {"CountType":"Sheets","ItemCount":1},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":0},
      {"CountType":"Other","ItemCount":1}
    ],
    [
      {"CountType":"Volumes","ItemCount":1},
      {"CountType":"Sheets","ItemCount":0},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":4},
      {"CountType":"Other","ItemCount":5}
    ]
]

要求的输出

总数

[
  {"CountType":"Volumes","ItemCount":5},
  {"CountType":"Sheets","ItemCount":7},
  {"CountType":"Photos","ItemCount":9},
  {"CountType":"Boxes","ItemCount":5},
  {"CountType":"Other","ItemCount":8}
]

更新:这是我尝试运行该功能的方式:

https://jsfiddle.net/yd051o76/2/

【问题讨论】:

  • 你的sumByProperty 函数看起来不错。请告诉我们你是如何在输入端调用它的

标签: javascript arrays ecmascript-6


【解决方案1】:

这可能是因为我需要遍历外部数组来对嵌套数组进行比较。

确实,您可以展平数组:

 function sumByProperty(items, prop) {
   return items.flat().reduce(function (a, b) {
     return b[prop] == null ? a : a + b[prop];
   }, 0);
 }

 const result = [
   { CountType: "Volumes", ItemCount: sumByProperty(input, "Volumes"), },
   //...
 ];

但我宁愿使用哈希表动态分组,这样你只需要迭代一次,你不需要命名所有属性:

  const hash = new Map();

   for(const { CountType, ItemCount } of input.flat())
      hash.set(CountType, (hash.get(CountType) || 0) + ItemCount);

  const result = [...hash.entries()].map(([CountType, ItemCount]) => ({ CountType, ItemCount }));

【讨论】:

  • 嘿-为什么是Map? :)
  • 因为它保证 O(1) 查找时间,因此是合适的数据结构。
  • 这并不能保证 O(1) 的查找时间(尽管大多数引擎会选择哈希表),但我更喜欢 Map 的明确性。
  • 有趣的信息 (+1) - 任何证明(或证明链接)?
  • 对于它的价值,MDN 的 Map 文档有一个部分 Objects and Maps compared。
【解决方案2】:

这是一个使用 2 个 reduce 函数和 for ... in ... 将结果合并回父级 reducer 的示例。

诀窍是确保您将累加器初始化为 null,以便您可以定义自己的累加器。然后,这只是减少数组数组并让另一个 reducer 运行对象数组的问题。完成后,您只需要将内部数组的结果合并回父级。 (可能是做这部分的更好方法)

小提琴:https://jsfiddle.net/mswilson4040/jcp9x6ba/26/

const json = [
  [
    {"CountType":"Volumes","ItemCount":3},
    {"CountType":"Sheets","ItemCount":6},
    {"CountType":"Photos","ItemCount":3},
    {"CountType":"Boxes","ItemCount":1},
    {"CountType":"Other","ItemCount":2}
  ],
  [
    {"CountType":"Volumes","ItemCount":1},
    {"CountType":"Sheets","ItemCount":1},
    {"CountType":"Photos","ItemCount":3},
    {"CountType":"Boxes","ItemCount":0},
    {"CountType":"Other","ItemCount":1}
  ],
  [
    {"CountType":"Volumes","ItemCount":1},
    {"CountType":"Sheets","ItemCount":0},
    {"CountType":"Photos","ItemCount":3},
    {"CountType":"Boxes","ItemCount":4},
    {"CountType":"Other","ItemCount":5}
  ]
];

const counts = json.reduce( (acc, currentArray) => {
	acc = acc ? acc : {};
  const arrCounts = currentArray.reduce( (_acc, _item) => {
  	_acc = _acc ? _acc : {};
    _acc[_item.CountType] = _acc[_item.CountType] ? _acc[_item.CountType] + _item.ItemCount : _item.ItemCount;
    return _acc;
  }, null);
  for (const item in arrCounts) {
  	acc[item] = acc[item] ? acc[item] + arrCounts[item] : arrCounts[item];
  }
  return acc;
}, null);


console.log(counts);

【讨论】:

    【解决方案3】:

    尝试(数据为输入,h = {},r为结果);

    data.map(a=> a.map(x=> h[x.CountType]=x.ItemCount+(h[x.CountType]||0) ))
    
    r= Object.keys(h).map(k=> ({CountType:k, ItemCount:h[k] }) );
    

    let data = [[
      {"CountType":"Volumes","ItemCount":3},
      {"CountType":"Sheets","ItemCount":6},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":1},
      {"CountType":"Other","ItemCount":2}
    ],
    [
      {"CountType":"Volumes","ItemCount":1},
      {"CountType":"Sheets","ItemCount":1},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":0},
      {"CountType":"Other","ItemCount":1}
    ],
    [
      {"CountType":"Volumes","ItemCount":1},
      {"CountType":"Sheets","ItemCount":0},
      {"CountType":"Photos","ItemCount":3},
      {"CountType":"Boxes","ItemCount":4},
      {"CountType":"Other","ItemCount":5}
    ]];
    
    let r,h = {};
    data.map(a=> a.map(x=> h[x.CountType]=x.ItemCount+(h[x.CountType]||0) ))
    r= Object.keys(h).map(k=> ({CountType:k, ItemCount:h[k] }) );
    
    console.log(r);

    【讨论】:

    • 这不是代码高尔夫。为什么h、r ...?这使事情变得不可读
    • 还有为什么.map?
    猜你喜欢
    • 2018-09-15
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多