如何按一个元素分组并在 Javascript 中找到另一个元素的平均值?

Posted

技术标签:

【中文标题】如何按一个元素分组并在 Javascript 中找到另一个元素的平均值?【英文标题】:How do I group by one element and find the average of another in Javascript? 【发布时间】:2021-09-12 02:08:28 【问题描述】:

我正在做一个项目,将葡萄酒的年龄与其分数进行比较,并希望制作一个折线图,X 轴为年份,Y 轴为每个年份的平均分数。我有一个对象数组,每个对象包含两个元素,年龄和分数,并希望按每个年龄分组并找到该年龄的平均分数。

我有一个通过 Global Wine Score 的请求创建的 CSV 文件,其中包含年份、评论日期、分数等。在 python 中,我通过从年份中减去评论年份来创建一个年龄列。在 javascript 中,我创建了一个新数组:

    var newArr = countryFilter.map(function(elem) 
            return 
                age: elem.wine_age,
                score: elem.score
            ;
        );

这是我的数组的样子:

0: Object  age: "116", score: "98.51" 

​​​​
age: "116"

​​​​
score: "98.51"

​​​
​​​
1: Object  age: "113", score: "84.46" 

​​​​
age: "113"

​​​​
score: "84.46"

length: 23258

我试过了,但是任何具有超过 1 个唯一分数的对象都会产生 NAN。

 const reduced = newArr.reduce(function(m, d)
        if(!m[d.age])
          m[d.age] = ...d, count: 1;
          return m;
        
        m[d.age].score += d.score;
        m[d.age].count += 1;
        return m;
     ,);

     const result = Object.keys(reduced).map(function(k)
         const item  = reduced[k];
         return 
             wine_age: item.age,
             score: item.score/item.count,
         
     )

     console.log(result);

我将如何找到每个酒龄的平均葡萄酒分数?

【问题讨论】:

【参考方案1】:

您可以按年龄将子数组中的对象分组,然后将子数组减少为具有平均分数的单个对象:

const input = [
   age: "113", score: "84.46" ,
   age: "113", score: "88.23" ,
   age: "112", score: "84.46" ,
   age: "113", score: "10.58" ,
];

const result = input
  .sort((a, b) => a.age - b.age)
  .reduce(
    (acc, cur, i,  [i - 1]: last ) =>
      cur.age === last?.age
        ? Object.assign([...acc], 
            [acc.length - 1]: [...acc[acc.length - 1], cur],
          )
        : [...acc, [cur]],
    []
  )
  .map((x) => (
    age: x[0].age,
    score: x.reduce((a, b) => a + Number(b.score), 0) / x.length,
  ));

console.log(result);

【讨论】:

嗨@Guerric P!不错的答案。仅出于学习目的,您能解释一下第一个reduce 方法的作用吗?我有点困惑,想完全理解答案。提前致谢。 第一个reduce目的是创建一个数组数组。每个数组仅包含具有特定年龄的对象。它认为该数组已经按年龄排序,并将当前项目的年龄与前一个项目的年龄进行比较。如果年龄相同,则将对象添加到最后一个子数组中,否则将其添加到新子数组中。【参考方案2】:

这是获得它的一种方法。你最终会得到一个年龄对象:平均对:

let grps= 
data.forEach(g => grps.hasOwnProperty(g.age)? // first we set up the age -> array of scores object
     grps[g.age].push(+g.score) : grps[g.age] = [+g.score]),
 avgs = Object.assign(...Object.entries(grps) // then we take that object and calculate the avg based on the total score tally / number of scores
     .map(g=>([g[0]]:
     (g[1].reduce((b,a)=> b+a)/grps[g[0]].length).toFixed(2)))) // reduce is a perfect vehicle for tallying up arrays of numbers.

let data = [
 age: "113", score: "84.46" ,
   age: "113", score: "88.23" ,
   age: "112", score: "84.46" ,
   age: "113", score: "10.58" ,
]
let grps=, s = data.forEach(g=>grps.hasOwnProperty(g.age)?grps[g.age].push(+g.score) : grps[g.age] = [+g.score]), avgs = Object.assign(...Object.entries(grps).map(g=>([g[0]]:(g[1].reduce((b,a)=> b+a)/grps[g[0]].length).toFixed(2))))
console.log(avgs)

【讨论】:

@GuerricP - 这不再正确,答案已修改。谢谢你叫出来,寿。当时对我来说似乎很有意义,但绝对是错误的方法

以上是关于如何按一个元素分组并在 Javascript 中找到另一个元素的平均值?的主要内容,如果未能解决你的问题,请参考以下文章

如何基于 ManyToManyField 内部连接表并按参数分组并在 Django 中获取最新的表?

如何正确使用 Muenchian 按元素对非常重复的标签进行分组?

如何按数组中的公共元素分组?

如何按n个元素对python中的元素进行分组[重复]

如何在javascript中将集合的元素分组为不相交的子集?

如何按定义的时间间隔对熊猫数据框进行分组?