Javascript:通过聚合分组

Javascript: group by with aggregation

本文关键字:Javascript      更新时间:2023-09-26

我有一个简单的json列表,就像下面的列表一样

{
"myList": [
    {
        "endOfPeriod": 1461362400000,
        "rate": 0.03726378
    },
    {
        "endOfPeriod": 1461535200000,
        "rate": 0.03726378
    },
    {
        "endOfPeriod": 1461967200000,
        "rate": 0.03708314
    },
    {
        "endOfPeriod": 1461708000000,
        "rate": 0.03492851
    },
    {
        "endOfPeriod": 1461794400000,
        "rate": 0.03845068
    },
    {
        "endOfPeriod": 1461621600000,
        "rate": 0.03544827
    }
]

}

其中endOfPeriod是unix历元时间戳。示例中的所有时间戳都属于同一个月(2016年4月),但可能是其他时间段。假设我已经将这个json列表转换为一个数组,并将每个unix时间戳转换为DD.MM.YYYY日期(我也可以将它们保存在unix时间戳中)。有没有一种有效的方法可以创建一个新的数组,该数组具有按月/年分组的最新速率?

我必须用Javascript编写代码。

例如:

20.04.2016 / 0.33
21.04.2016 / 0.55
14.04.2016 / 0.88
02.05.2016 / 1.33
01.05.2016 / 5.44

新数组必须包含:

21.04.2016 / 0.55
02.05.2016 / 1.33

谢谢你的帮助。

如果我理解正确,您需要提取每个月的最新费率。我会使用lodash

_.chain(arr)
  .groupBy(function(item) {
    var date = new Date(item.endOfPeriod);
    return date.getFullYear() + '-' + date.getMonth();
  })
  .map(function(group) {
    return _.maxBy(group, function(item) {
      return item.endOfPeriod;
    });
  })
  .value()

我们从以下形式的对象列表开始:

{
    "endOfPeriod" : 1464818400000,
    "rate" : 0.05
}

chain()函数将列表封装到一个lodash对象中。

然后,我们按年份和月份对元素进行分组。在groupBy()之后,我们有以下结构(注意getMonth()在Javascript中是基于0的,因此值3对应于April,依此类推):

{
  "2016-3" : [array of objects in April 2016],
  "2016-4" : [array of objects in May 2016]
  ...
}

然后,对于每组,我们取具有最大endOfPeriod的项目。

最后,value()将lodash对象展开为一个普通的Javascript数组。

这是一个不使用lodash的结果。但对我来说,最好不要重新发明轮子。

const myList = [
  {
    "endOfPeriod": 1461362400000,
    "rate": 0.03726378
  },
  {
    "endOfPeriod": 1461535200000,
    "rate": 0.03726378
  },
  {
    "endOfPeriod": 1461967200000,
    "rate": 0.03708314
  },
  {
    "endOfPeriod": 1461708000000,
    "rate": 0.03492851
  },
  {
    "endOfPeriod": 1461794400000,
    "rate": 0.03845068
  },
  {
    "endOfPeriod": 1461621600000,
    "rate": 0.03544827
  }
];
const res = myList.reduce((prev, current) => {
  const date = new Date(current.endOfPeriod);
  const month = date.getMonth();
  const year = date.getFullYear();
  const key = `${year}-${month}`;
  if (prev[key] && prev[key].endOfPeriod < current.endOfPeriod) {
    prev[key] = current;
  } else {
    prev[key] = current;
  }
    return prev;
}, {});

const finalResult = Object.keys(res).map((key) => {
  return {
    key: res[key].rate
  }
});
console.log(finalResult);