You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JSONata优雅实现按时间重组时序数据层级?

时序数据层级翻转的JSONata优化方案

需求说明

需要将按系列分组的时序数据,转换为按时间戳分组的结构:原始数据中每个系列包含独立的data数组(元素含time和value),目标是生成一个对象数组,每个对象以time为标识,同时包含所有系列对应时间点的数值。

原始数据

{
  "series1": {
    "data": [
      {"time": "2024-01-01T00:00:00Z", "value": 10},
      {"time": "2024-01-02T00:00:00Z", "value": 20}
    ]
  },
  "series2": {
    "data": [
      {"time": "2024-01-01T00:00:00Z", "value": 100},
      {"time": "2024-01-02T00:00:00Z", "value": 200}
    ]
  }
}

目标输出

[
  {"time": "2024-01-01T00:00:00Z", "series1": 10, "series2": 100},
  {"time": "2024-01-02T00:00:00Z", "series1": 20, "series2": 200}
]

常见初始实现(参考)

如果你的当前实现是类似硬编码系列名称、手动查找时间匹配值的写法,比如:

$map(
  $distinct($.series1.data.time & $.series2.data.time),
  function($t) {
    {
      "time": $t,
      "series1": ($.series1.data[$time = $t].value)[0],
      "series2": ($.series2.data[$time = $t].value)[0]
    }
  }
)

这种写法的问题是扩展性差——新增系列时需要修改表达式,且多次查找效率较低。

优化后的JSONata表达式

$map(
  $groupBy(
    $flatten($.($map(data, function($d) { $merge([$d, {series: $$}]) }))),
    "time"
  ),
  function($group, $time) {
    {"time": $time} & $reduce($group, function($acc, $item) {
      $acc & {$item.series: $item.value}
    }, {})
  }
)

优化点说明

  1. 动态适配任意系列数量:通过$.($map(data, ...))遍历所有顶层系列,不需要硬编码series1/series2,新增系列时无需修改表达式。
  2. 高效分组:用$groupBy直接按time对所有数据项分组,替代手动去重时间+逐个查找的繁琐逻辑。
  3. 简洁对象合并:使用JSONata的&操作符简化对象合并,比$merge更直观;$reduce动态构建每个时间点的系列数值字段。

更精简的版本

如果追求极致简洁,还可以写成:

$map($groupBy($flatten($.data~>$map(function($d) { $d & {series: $$} })), "time"), function($g, $t) { {"time": $t} & $g~>$reduce(function($a, $v) { $a & {$v.series: $v.value} }, {}) })

内容的提问来源于stack exchange,提问作者Svet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:31:01