首页 > 解决方案 > JSON 解析 - 使用 JQ 按日期范围分组

问题描述

我有以下 JSON 数据:

{
  "data": [  
    {"date": "2018-08-22","value": 1},
    {"date": "2018-08-30","value": 2},
    {"date": "2018-09-01","value": 3},
    {"date": "2018-09-22","value": 3},
    {"date": "2018-09-28","value": 4},
    {"date": "2018-10-18","value": 5},
    {"date": "2018-10-23","value": 6}
  ]
}

我想使用 JQ 从第一个值开始每月对数据进行分组:我的月份是:

我的预期输出如下:

{
  "data": [  
    {"month": "2018-08-22 to 2018-09-21","sum": 6},
    {"month": "2018-09-22 to 2018-10-21","sum": 12},
    {"month": "2018-10-23 to 2018-11-21","sum": 6}
  ]
}

我怎样才能做到这一点 ?

标签: jsondategroupingaggregatejq

解决方案


使用以下辅助函数很容易获得解决方案:

# $day should be the day (an integer) that defines the cutoff point;
# input should be a Y-M-D string
def bucket($day):
  def prev: if .m > 1 then .m -= 1 else .m = 12 | .y -= 1 end;
  def fmt: if .m <= 9 then "\(.y)-0\(.m)" else "\(.y)-\(.m)" end;
  capture("(?<y>[0-9]+)-(?<m>[0-9]+)-(?<d>[0-9]+)")
  | map_values(tonumber)
  | if .d >= $day then . else prev end
  | fmt ;

我们现在计算桶数对:

.data
| (.[0].date | capture("(?<d>[0-9]+)$") | .d | tonumber) as $day
| reduce .[] as $pair ({};
  .[$pair.date | bucket($day)] += ($pair.value) )

使用样本数据,这会产生:

{
  "2018-08": 6,
  "2018-09": 12,
  "2018-10": 6
}      

现在将其转换为所需的格式是一件小事,因此留作练习。


推荐阅读