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)