Home > database >  Reducing after filtering doesn't add up with jq
Reducing after filtering doesn't add up with jq

Time:12-15

I have the following data:

[
  {
    "name": "example-1",
    "amount": 4
  },
  {
    "name": "foo",
    "amount": 42
  },
  {
    "name": "example-2",
    "amount": 6
  }
]

I would like to filter objects with a .name containing "example" and reduce the .amount property.

This is what I tried to do:

json='[{"name":"example-1","amount":4}, {"name": "foo","amount":42}, {"name": "example-2","amount":6}]'

echo $json | jq '.[] | select(.name | contains("example")) | .amount | add'

I get this error:

jq: error (at :1): Cannot iterate over number (4)

I think that the output of .[] | select(.name | contains("example")) | .amount is a stream, and not an array, so I cannot add the values together.

But how could I do to output an array instead, after the select and the lookup?

I know there is a map function and map(.amount) | add works, but the filtering isn't here.

I can't do a select without .[] | before, and I think that's where the "stream" problem comes from...

CodePudding user response:

As you say, add/0 expects an array as input.

Since it's a useful idiom, consider using map(select(_)):

echo "$json" | jq 'map(select(.name | contains("example")) | .amount) | add'

However, sometimes it's better to use a stream-oriented approach:

def add(s): reduce s as $x (null; .   $x); 

add(.[] | select(.name | contains("example")) | .amount)
  • Related