如何通过特定对象键对数组中的值进行求和?

5

我有一个JavaScript对象数组,看起来像这样:

var objArr = [
     {"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
   ]

我想创建一个新数组,其中国家是唯一的,同时日期应该被累加。
{"Country": "US", "2017-07-12":  "3", "2017-07-13": "4"},
{"Country": "CN", "2017-07-12": "10", "2017-07-13": "14"}
            ^^^^                ^^^^                ^^^^   

我对它感到困惑。我是否需要先进行过滤、缩减,然后重新映射等操作?我不知道该从哪里开始。非常感谢任何帮助!


哦,那样的话,您只需要按国家对条目进行分组,然后对相同属性的值进行求和。 - VLAZ
这个回答解决了你的问题吗?在对象数组上进行分组的最有效方法 - VLAZ
特别是,您可以查看Scott Sauyet的答案,该答案提供了一种更灵活的方法。其他一些答案还展示了如何进行分组和转换。 - VLAZ
3个回答

3
使用 Array.reduce,检查当前国家的对象是否存在,如果存在,则循环遍历 Object.keys 来更新值,如果不存在,则推入一个新对象: 编辑:如果不需要 City 可以解构它 {City, ...curr}

var objArr = [
  { Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
  { Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
  { Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
  { Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];

var result = objArr.reduce((acc, {City, ...curr}) => {
  const ndx = acc.findIndex(e => e.Country === curr.Country);
  if (ndx > -1) {
    const [country, ...keys] = Object.keys(curr);
    keys.forEach(k => {
      acc[ndx][k] = +acc[ndx][k] + +curr[k];
    });
  } else {
    acc.push(curr);
  }
  return acc;
}, []);

console.log(result);


Op 不想在结果中包含城市。 - Maheer Ali

0
你可以使用 reduce() 创建一个对象来分组元素,然后使用 Object.values

var objArr = [
     {"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
   ]

let keys = ["2017-07-12", "2017-07-13"];
const res = Object.values(objArr.reduce((ac, a) => {
  if(!ac[a.Country]){
    ac[a.Country] = {Country: a.Country};
  }

  keys.forEach(k => {
    ac[a.Country][k] = (ac[a.Country][k] || 0) + Number(a[k]);
  })
  return ac;
}, {}))
console.log(res)


0
使用一个forEach循环数组,并使用forEach遍历每个对象日期键,使用唯一键Country和累积值构建一个res对象。 使用Object.valuesres对象获取数组。
更新:修复确保日期始终为number类型。

var objArr = [
  { Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
  { Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
  { Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
  { Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];

const update = data => {
  const res = {};
  data.forEach(({ Country, City, ...dates }) => {
    const item = res[Country] || { Country };
    Object.keys(dates).forEach(date => {
      item[date] = (item[date] || 0) + Number(dates[date]);
    });
    res[Country] = { ...item };
  });
  return Object.values(res);
};

console.log(update(objArr));


在我的一些结果中,有些值是字符串,有些是整数。这正常吗? 国家:"中国" 3/1/20: 79826 3/2/20: 80026 1: 国家:"泰国" 1/22/20: "2" 1/23/20: "3" - Jan
1
@Jan,我明白了。我认为最好是所有项目使用相同的类型。在这里,我觉得数字更好。我更新了答案,以确保始终使用数字。 - Siva K V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接