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

Posted

技术标签:

【中文标题】如何通过特定对象键对数组中的值求和?【英文标题】:How to sum values in array by specific object key? 【发布时间】:2020-06-14 21:45:45 【问题描述】:

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

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"
            ^^^^                ^^^^                ^^^^   

我很难理解它。 我必须先过滤,以某种方式减少它,重新映射它,......我不知道开始吗? 任何帮助将不胜感激,谢谢!

【问题讨论】:

哦,在这种情况下,您只需按国家/地区对条目进行分组,然后将相同属性的值相加 这能回答你的问题吗? Most efficient method to groupby on an array of objects 特别是,您可以查看Scott Sauyet's answer,它提供了一种更灵活的方法。其他一些还展示了如何分组和转换。 【参考方案1】:

对数组使用一个forEach 并使用forEach 遍历每个对象的日期键,并使用唯一键为Country 和累积值构建一个res 对象。 使用 Object.values 的 res 从 res 对象中获取数组。

更新:修复以确保始终使用一种日期类型,即 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:国家:“泰国”2020 年 1 月 22 日:“2” 2020 年 1 月 23 日:“3” @Jan,哦,我明白了。我认为最好有相同类型的物品。在这里我认为数字更好。我更新了答案以确保始终有数字。【参考方案2】:

使用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 不想在结果中显示城市【参考方案3】:

您可以使用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)

【讨论】:

以上是关于如何通过特定对象键对数组中的值求和?的主要内容,如果未能解决你的问题,请参考以下文章

使用字典中的键对对象数组进行排序

如何用特定键对数组值求和[重复]

PHP按另一个数组中的特定键对数组进行排序[重复]

Python:通过每个国家的Json数据中的键求和的值

按数组中的多个属性对对象进行分组,然后将它们的值相加

如何从 PostgreSQL 中的 JSONB 数组中获取特定对象的值?