如何通过键将值收集到数组中?

友人A*_*友人A 7 text-processing json jq

给定条目格式的输入,可能具有重复的键,例如

[
  {"key": "a", "value": 0},
  {"key": "a", "value": 1},
  {"key": "a", "value": 2},
  {"key": "b", "value": 3},
  {"key": "b", "value": 4},
  {"key": "b", "value": 5}
]
Run Code Online (Sandbox Code Playgroud)

我想生产

{"a": [0, 1, 2], "b": [3, 4, 5]}
Run Code Online (Sandbox Code Playgroud)

即,针对每个唯一键将具有相同键的所有值收集在数组中。

我怎样才能做到这一点jq

Kus*_*nda 10

使用reduce()in通过将给定值添加到值给定的键jq来逐渐构建结果对象:valuekey

$ jq -c 'reduce .[] as $a ({}; .[$a.key] += [$a.value])' file
{"a":[0,1,2],"b":[3,4,5]}
Run Code Online (Sandbox Code Playgroud)

reduce()行为就像一种循环,在本例中,它迭代.[],即顶级数组中的所有对象。对于每个对象 ,$a值都会添加到键 下的$a.value结果对象(最初是空对象)中。{}$a.key


对于喜欢使用 的人来说,还有一个提示jq:通过使用debug,您可以在表达式运行时查看表达式中任意点的数据。在这里,我正在研究循环中每次迭代后累加器对象的状态reduce()

$ jq -c 'reduce .[] as $a ({}; .[$a.key] += [$a.value] | debug)' file
["DEBUG:",{"a":[0]}]
["DEBUG:",{"a":[0,1]}]
["DEBUG:",{"a":[0,1,2]}]
["DEBUG:",{"a":[0,1,2],"b":[3]}]
["DEBUG:",{"a":[0,1,2],"b":[3,4]}]
["DEBUG:",{"a":[0,1,2],"b":[3,4,5]}]
{"a":[0,1,2],"b":[3,4,5]}
Run Code Online (Sandbox Code Playgroud)

$a在这里,我正在研究每次迭代中分配的值:

$ jq -c 'reduce (.[]|debug) as $a ({}; .[$a.key] += [$a.value])' file
["DEBUG:",{"key":"a","value":0}]
["DEBUG:",{"key":"a","value":1}]
["DEBUG:",{"key":"a","value":2}]
["DEBUG:",{"key":"b","value":3}]
["DEBUG:",{"key":"b","value":4}]
["DEBUG:",{"key":"b","value":5}]
{"a":[0,1,2],"b":[3,4,5]}
Run Code Online (Sandbox Code Playgroud)


pro*_*tob 7

您可以使用group_by,mapfrom_entries

jq 'group_by(.key) | map({key: .[0].key, value: [.[].value]}) | from_entries' data.json 
Run Code Online (Sandbox Code Playgroud)