如何使用jq以相同的键合并/连接/连接值

时间:2017-04-19 17:54:37

标签: json join merge concat jq

我需要按键聚合值。示例JSON输入是:

$ cat json | jq 
[
  {
    "key": "john",
    "value": "ontario"
  },
  {
    "key": "ryan",
    "value": "chicago"
  },
  {
    "key": "ryan",
    "value": "illinois"
  },
  {
    "key": "john",
    "value": "toronto"
  },
]

是否可以,如果可以,如何使用相同的键合并/连接/连接值,以便结果为:

[
  {
    "key": "john",
    "value": "toronto ontario"
  },
  {
    "key": "ryan",
    "value": "illinois chicago"
  },
]

我特别针对JQ,因为它易于使用cfengine。

2 个答案:

答案 0 :(得分:1)

按键对对进行分组,然后合并值。

group_by(.key) | map({key:.[0].key,value:(map(.value) | join(" "))})

答案 1 :(得分:0)

对于这类问题,我更喜欢避免排序的开销,并保证输入中对象的排序得到遵守。

这是一种假设与“key”和“value”相关联的值都是字符串的方法(如示例中的情况)。这个假设可以很容易地避免低效的查找:

def merge_by_key(separator):
  reduce .[] as $o
    ({}; $o["key"] as $k
         | if .[$k] then .[$k] += (separator + $o["value"])
           else .[$k] = $o["value"] end);

merge_by_key(" ") | to_entries

输出:

[{"key":"john","value":"ontario toronto"},
 {"key":"ryan","value":"chicago illinois"}]

通用解决方案

def merge_at_key(separator):
  reduce .[] as $o
    ([];
     $o["key"] as $k
     | (map(.key) | index($k)) as $i
     | if $i then (.[$i] | .value) += (separator + $o["value"])
       else . + [$o] end);