0

I have a stream of JSON arrays like this

[{"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}]

I want to use jq to get a new json like this

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

34=1+3+13+12+5 which are in the second array. I don't know how to describe it in detail. But the basic idea is shown in my example. I use bash and prefer to use jq to solve this problem. Thank you!

peak
  • 105,803
  • 17
  • 152
  • 177
Eleanor
  • 2,647
  • 5
  • 18
  • 30

3 Answers3

2

If you want an efficient but generic solution that does NOT assume each input array has the same ids, then the following helper function makes a solution easy:

# 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));

Assuming your jq has inputs, then the most efficient approach is to use it (but remember to use the -n command-line option):

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

This produces:

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

From here, it's easy to get the answer you want, e.g. using to_entries[] | {(.key): .value}

If your jq does not have inputs and if you don't want to upgrade, then use the -s option (instead of -n) and replace inputs by .[]

peak
  • 105,803
  • 17
  • 152
  • 177
1

Assuming the .id is the same in each array:

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

Or perhaps more intelligibly:

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

Or more declaratively:

{ id: (first|.id), Count: (map(.Count) | add) }
peak
  • 105,803
  • 17
  • 152
  • 177
0

It's a bit kludgey, but given your input:

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

Yields the output:

{"id":"AQ","Count":0}
{"id":"AR","Count":34}
{"id":"AS","Count":0}
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • you know that jq has a function add right? I was thinking if I could use jq 'map(.Count) | add' which returns 0 34 0 and then give these 3 number a key "Count". But I don't to know how to add value to a new key.... – Eleanor Jul 19 '17 at 15:40
  • I would try your method first! – Eleanor Jul 19 '17 at 15:40