【问题标题】:Aggregate an array of objects in JavaScript在 JavaScript 中聚合对象数组
【发布时间】:2020-02-14 13:30:18
【问题描述】:

我有一个包含布尔字段 X 的对象数组。[{..., x: true, y: 3, ...]

如果x所有值对应true(或@987654326 @),否则 undefined... 和 y 的总和...

是否可以使用reduce Array 函数、groupby by underscorejs 或其他用于此目的的函数?

例如:

[
 {a:'titi', x: true,  y: 3}, 
 {a:'toto', x: false, y: 6}
]

结果

       {x: undefined, y: 9}

【问题讨论】:

  • @georg,这不仅仅是一个单一的操作,而是一个复杂的对象......
  • 好的,我明白了,重新打开

标签: javascript arrays aggregation


【解决方案1】:

reduce 非常简单:

.reduce((a, b) => ({
   x: a.x == b.x ? a.x : undefined,
   y: a.y + b.y
}))

活生生的例子:

var input = [
       {a:'titi', x: true,  y: 3}, 
       {a:'toto', x: false, y: 6}
    ];
    
console.log(input.reduce((a, b) => ({
   x: a.x == b.x ? a.x : undefined,
   y: a.y + b.y
})));

【讨论】:

  • 这很酷,当然它会创建一堆不必要的对象。不过,99.9% 的时间都没有关系。
【解决方案2】:

我使用reduce 提出了这个解决方案。似乎有点hacky,但它应该可以完成这项工作。在缩减数组时,它会确定每个 x 值是否相等,然后相应地设置缩减对象的 x 值。

let reduced = arr.reduce((acc, curr) => {
    acc.x &= acc.x_init === curr.x;
    acc.y += curr.y;
  }, {x_init: arr[0].x, x: true, y: 0});
reduced.x = reduced.x ? reduced.x_init : undefined;
delete reduced.x_init;

【讨论】:

    【解决方案3】:

    虽然您可以将其塞入reduce 调用中(因为任何数组操作都可以塞入reduce),但这样做没有任何好处。只需使用循环:

    const result = {x: null, y: 0};
    for (const entry of array) {
        if (result.x === null) {
            result.x = entry.x;
        } else if (result.x !== entry.x) {
            result.x = undefined;
        }
        result.y += entry.y;
    }
    

    现场示例:

    function check(array) {
        const result = {x: null, y: 0};
        for (const entry of array) {
            if (result.x === null) {
                result.x = entry.x;
            } else if (result.x !== entry.x) {
                result.x = undefined;
            }
            result.y += entry.y;
        }
        console.log(result);
    }
    check([
     {a:'titi', x: true,  y: 3}, 
     {a:'toto', x: false, y: 6}
    ]);
    console.log("---");
    check([
     {a:'titi', x: true,  y: 3}, 
     {a:'toto', x: true, y: 6}
    ]);
    console.log("---");
    check([
     {a:'titi', x: false,  y: 3}, 
     {a:'toto', x: false, y: 6}
    ]);
    console.log("---");

    但是,如果您愿意,您可以通过始终返回相同的对象将其硬塞到 reduce

    const result = array.reduce((obj, entry) => {
        if (obj.x === null) {
            obj.x = entry.x;
        } else if (obj.x !== entry.x) {
            obj.x = undefined;
        }
        obj.y += entry.y;
        return obj;
    }, {x: null, y: 0});
    

    现场示例:

    function check(array) {
        const result = array.reduce((obj, entry) => {
            if (obj.x === null) {
                obj.x = entry.x;
            } else if (obj.x !== entry.x) {
                obj.x = undefined;
            }
            obj.y += entry.y;
            return obj;
        }, {x: null, y: 0});
        console.log(result);
    }
    check([
     {a:'titi', x: true,  y: 3}, 
     {a:'toto', x: false, y: 6}
    ]);
    console.log("---");
    check([
     {a:'titi', x: true,  y: 3}, 
     {a:'toto', x: true, y: 6}
    ]);
    console.log("---");
    check([
     {a:'titi', x: false,  y: 3}, 
     {a:'toto', x: false, y: 6}
    ]);
    console.log("---");

    但是,如果您想要reduce 解决方案并且不介意创建一堆临时丢弃对象,请查看Adassko's answer。简单直接,而且在 99.9% 的情况下,您都不关心临时对象的创建。

    【讨论】:

      【解决方案4】:

      感谢@Adassko,我的变种有点长:

      [
        {a:'titi', x: false,  y: 3}, 
        {a:'toto', x: false, y: 6}
      ]
      .reduce((a, b, i) => ({
        x : a.x === b.x || i == 0 ? b.x : undefined,
        y : a.y + b.y
      }))
      

      【讨论】:

        猜你喜欢
        • 2011-09-17
        • 2018-04-20
        • 1970-01-01
        • 2021-06-21
        • 1970-01-01
        • 1970-01-01
        • 2017-02-14
        • 1970-01-01
        • 2021-04-27
        相关资源
        最近更新 更多