JavaScript-在多个相同长度的对象数组中组合和添加值

时间:2018-12-17 03:52:36

标签: javascript arrays

我希望通过匹配相同的日期字符串来减少对象数组,并将这些匹配日期的总数相加,然后将它们组合成一个对象。我可以将阵列放置成几千个项目,所以我试图增加(在可能的情况下)和复杂性。

// before
let objArr = [
    {
        date: '01/01/2018',
        total: 1
    },
    {
        date: '01/01/2018',
        total: 2
    },
    {
        date: '01/02/2018',
        total: 3
    },
    {
        date: '01/02/2018',
        total: 4
    },
    ...
]

// final result
let finalArr = [
    {
        date: '01/01/2018',
        total: 3
    },
    {
        date: '01/02/2018',
        total: 7
    },
    ...
]

我似乎无法掌握使用reduce减少它​​们的习惯:

objArr.reduce((acc, obj) => {
      acc.set(obj.date, (acc.get([obj.date]) || 0) + obj.total);
      return acc;
    }, new Map())

结果总是以错误的总数结尾,或者最后几个数组对象看起来像:

// bad output
badArray = [
    ...,
    {
        date: '01/02/2018',
        total: 4
    },
    {
        date: undefined,
        total: NaN
    },
    {
        date: undefined,
        total: NaN
    }
]

我编写了一个脚本来检查以确保datetotal属性中的所有值都以它们所需的方式存在,但是我仍然遇到了错误的数组。这里的假设是我的reduce函数不正确。

2 个答案:

答案 0 :(得分:3)

您的代码几乎正确。问题是您将Map键设置为日期,但是尝试通过传递带有日期而不是单独日期的数组来get

您可能正在使用:acc.get([obj.date])acc.get(obj.date)(没有[ ])时使用

let objArr = [{date: '01/01/2018',total: 1},{date: '01/01/2018',total: 2},{date: '01/02/2018',total: 3},{date: '01/02/2018',total: 4},]

let s = objArr.reduce((acc, obj) => {
    // not acc.get([obj.date]) !
    acc.set(obj.date, (acc.get(obj.date) || 0) + obj.total);
    return acc;
  }, new Map())

// turn the Map into something that will display:
console.log([...s.entries()].map(([date, total]) => ({date, total})))

答案 1 :(得分:0)

我认为Mark Meyer的答案很好,但这也是另一个选择,它使用空数组作为初始值而不是Map(始终保持输入的原始结构):

 let objArr = [{date: '01/01/2018',total: 1},{date: '01/01/2018',total: 2},{date: '01/02/2018',total: 3},{date: '01/02/2018',total: 4},];
    
 const result = objArr.reduce((acc, obj) => {
     const existingObj = acc.find((o) => o.date === obj.date);
     if (existingObj) {
       existingObj.total += obj.total;
     } else {
       acc.push(obj);
     }
     return acc;
 }, []);
    
 console.log(result);

请注意,使用空数组作为初始值的好处是它可以保持输入的原始结构(因此,您不必随后遍历生成的Map并将其转换为对象数组)。 :)