将数组中的对象合并为一个

时间:2019-06-21 10:03:23

标签: javascript

我有一个对象数组,如下所示:

arr = [  
    {  
        totalPrice:{  
            value:5,
            currencyId:0
        }
    },
    {  
        totalPrice:{  
            value:1,
            currencyId:0
        }
    },
    {  
        totalPrice:{  
            value:6,
            currencyId:0
        }
    }
]

如果所有的totalPrice对象都具有相同的currencyId,我想做的就是得到一个包含值总和的单个对象(totalPrice)。

第一步是确定所有totalPrice对象是否具有相同的currencyId:

var canBeMerged = arr.every(l => l.totalPrice.currencyId === arr[0].totalPrice.currencyId);

然后:

var merged = null;

if(canBeMerged){
    var valueSum = 0;

    for (var k=0; k<arr.length; k++) {
      valueSum += arr[k].totalPrice.value;
    }
      merged = {value: valueSum, currencyId: arr[0].totalPrice.currencyId}
}

是否有一种方法可以用一种方法完成所有这些工作?我认为reduce函数可以做到这一点,但我不知道该怎么做。

任何帮助将不胜感激:)

3 个答案:

答案 0 :(得分:0)

let merged = {
  value: arr.
    filter(e => e.totalPrice.currencyId === arr[0].totalPrice.currencyId).
    reduce((a, b) => a + b.totalPrice.value, 0),
  currencyId: arr[0].totalPrice.currencyId
};

我们首先使用{{1}过滤掉arr数组的所有条目,其中属性totalPrice.currencyIdarr数组中第一个条目的属性不匹配}。 filter返回一个新的过滤项目数组。我们可以链接filter来汇总此过滤数组中的值。

答案 1 :(得分:0)

这使用一个对象来累加每个currencyId的值。

let merge = arr => {
  d = {};
  arr.forEach(a => d[a.totalPrice.currencyId] = (d[a.totalPrice.currencyId] ? d[a.totalPrice.currencyId] : 0) + a.totalPrice.value);
  return Object.entries(d).map(([k, i]) => ({ value: i, currencyId: parseInt(k) }));
}

示例:

>> arr = [  
        {  
            totalPrice:{  
                value:5,
                currencyId:0
            }
        },
        {  
            totalPrice:{  
                value:1,
                currencyId:0
            }
        },
        {  
            totalPrice:{  
                value:6,
                currencyId:0
            }
        }
    ]

>> merge(arr)
 [{ value:12, currencyId:0 }]

>> arr = [  
        {  
            totalPrice:{  
                value:5,
                currencyId:0
            }
        },
        {  
            totalPrice:{  
                value:1,
                currencyId:1
            }
        },
        {  
            totalPrice:{  
                value:6,
                currencyId:0
            }
        }
    ]

>> merge(arr)
 [{ value:11, currencyId:0 }, { value:1, currencyId:1 }]

答案 2 :(得分:-1)

以下是功能样式的示例:

pipe = (...fns) => obj => fns.reduce((r, f) => r === null ? null : f(r), obj);
ifAll = fn => a => a.every(fn) ? a : null;
pick = prop => a => a.map(x => x[prop]);
sum = a => a.reduce((x, y) => x + y, 0);

//

sumCurr = pipe(
    pick('totalPrice'),
    ifAll(x => x.currencyId === 0),
    pick('value'),
    sum,
);

//

arr = [
    {
        totalPrice:{
            value:5,
            currencyId:0
        }
    },
    {
        totalPrice:{
            value:1,
            currencyId:0
        }
    },
    {
        totalPrice:{
            value:6,
            currencyId:0
        }
    }
]

console.log(sumCurr(arr))

尽管我实际上会使用lodash或ramda之类的库,但已经提供了这类内容。

如果目标不支持everysome,可以用reduce轻松表示它们:

 every = (a, f) => a.reduce((r, x) => r && f(x), true);
 some  = (a, f) => a.reduce((r, x) => r || f(x), false);