Javascript:使用聚合分组

时间:2016-05-01 09:40:10

标签: javascript json group-by

我有一个简单的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

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您想要提取每个月的最新费率。我会使用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数组。

答案 1 :(得分:0)

以下是不使用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);