首页 > 解决方案 > 根据日期字段的年份对数据进行分组和计数

问题描述

我有这个数据集:

const data = [ 
  {animal: 'cat', name: 'mu', date: new Date(2020, 0, 1)},
  {animal: 'cat', name: 'muji', date: new Date(2021, 0, 1)},
  {animal: 'cat', name: 'mine', date: new Date(2021, 0, 1)},
  {animal: 'dog', name: 'fido', date: new Date(2021, 0, 1)}, 
  {animal: 'dog', name: 'fido2', date: new Date(2020, 0, 1)}, 
  {animal: 'dog', name: 'fido3', date: new Date(2021, 0, 1)}, 
  {animal: 'hamster', name: 'gerry', date: new Date(2019, 0, 1)}, 
  {animal: 't-rex', name: 'dino', date: new Date(2020, 0, 1)},
  {animal: 't-rex', name: 'sauro', date: new Date(2019, 0, 1)},
  {animal: 'sheep', name: 's', date: new Date(2019, 0, 1)}, 
  {animal: 'sheep', name: 'sss', date: new Date(2019, 0, 1)}, 
]

它基本上是一个对象数组。每个对象都包含一个date带有日期对象的字段。

我想要的是这样的:

const result = {
  cat: {2020: 1, 2021: 2},
  dog: {2020: 1, 2021: 2},
  hamster: {2019: 1},
  't-rex': {2019: 1, 2020: 1},
  sheep: {2019: 2},
}

因此,按animal每个动物值分组的对象是一个对象,其包含每年的键,值是该年份的记录数。

如您所见,cat2021 年有 2 个日期,2020 年有 1 个日期cat: {2020: 1, 2021: 2}

我想我可以使用d3.rollup并执行以下操作:

const result = d3.rollup(data, v => v.?, d => d.animal)

我不知道如何使用,或者也许有更聪明的解决方案,我也可以使用 Lodash。

非常感谢任何帮助!

标签: javascriptd3.jslodash

解决方案


这确实很容易d3.rollup

result = d3.rollup(data, v => v.length, v => v.animal, v => v.date.getFullYear())

这为您提供了嵌套Map的 s,如果您出于某种原因想要对象,请像这样转换地图:

objects = Object.fromEntries(
    Array.from(result, ([k, v]) => 
        [k, Object.fromEntries(v)]))

如果你不想要 d3 依赖,你可以rollup用 vanilla JS 重写:

function rollup(data, reducer, grouper, ...groupers) {
    let m = new Map

    if (!grouper)
        return reducer(data)

    for (let item of data) {
        let key = grouper(item)
        m.has(key) ? m.get(key).push(item) : m.set(key, [item])
    }

    for (let [k, v] of m)
        m.set(k, rollup(v, reducer, ...groupers))

    return m
}

最后,如果您正在寻找简单而快速的代码而不是“智能”代码,您可以简单地迭代一次并直接填充嵌套对象(这是nullish assignment ??=派上用场的地方):

const result = {}

for (let obj of data) {
    let k1 = obj.animal,
        k2 = obj.date.getFullYear()

    result[k1] ??= {}
    result[k1][k2] ??= 0
    result[k1][k2]++
}

推荐阅读