jq在嵌套数组中添加键的值并赋予新键

时间:2017-07-19 15:25:24

标签: json bash addition jq ndjson

我有像这样的JSON数组流

[{"id":"AQ","Count":0}]
[{"id":"AR","Count":1},{"id":"AR","Count":3},{"id":"AR","Count":13},
{"id":"AR","Count":12},{"id":"AR","Count":5}]
[{"id":"AS","Count":0}]

我想用jq来获取像这样的新json

{"id":"AQ","Count":0}
{"id":"AR","Count":34}
{"id":"AS","Count":0}

34 = 1 + 3 + 13 + 12 + 5,它们位于第二阵列中。 我不知道如何详细描述它。但是我的例子中显示了基本思想。 我使用bash并且更喜欢使用jq来解决这个问题。谢谢!

3 个答案:

答案 0 :(得分:2)

如果您想要一个高效但通用的解决方案,并不假设每个输入数组都具有相同的ID,那么以下辅助函数可以使解决方案变得简单:

# Input: a JSON object representing the subtotals
# Output: the object augmented with additional subtotals
def adder(stream; id; filter):
  reduce stream as $s (.; .[$s|id] += ($s|filter));

假设您的jq有inputs,那么最有效的方法是使用它(但请记住使用-n命令行选项):

reduce inputs as $row ({}; adder($row[]; .id; .Count) )

这会产生:

{"AQ":0,"AR":34,"AS":0}

从这里,您可以轻松获得所需的答案,例如:使用to_entries[] | {(.key): .value}

如果您的jq没有inputs并且您不想升级,请使用-s选项(而不是-n)并将inputs替换为.[] }

答案 1 :(得分:1)

假设每个数组中的.id相同:

first + {Count: map(.Count) | add}

或许更可理解:

(map(.Count) | add) as $sum | first | .Count = $sum

或更具声明性:

{ id: (first|.id), Count: (map(.Count) | add) }

答案 2 :(得分:0)

这有点像kludgey,但是根据你的意见:

jq -c '
  reduce .[] as $item ({}; .[($item.id)] += ($item.Count))
  | to_entries
  | .[] | {"id": .key, "Count": .value}
'

产生输出:

{"id":"AQ","Count":0}
{"id":"AR","Count":34}
{"id":"AS","Count":0}