Reputation: 1789
My json file is called my_locations.json
and contains an array called locations
. I want to filter this array by all objects that have keys location.is_shop
and location.has_parking_space
. I then want to return the length of this filtered array.
Here is my attempt using the program jq
:
$ jq ".locations[] | select(.is_shop and .has_parking_space) | length" my_locations.json
13
13
13
13
13
...
13
So it outputs the length of each location object in the array instead of the length of the filtered array.
How can I return the length of the filtered array?
Upvotes: 2
Views: 1776
Reputation: 189
Just stumble into this post and I discovered another solution. You can pass --indent 0
to jq
(so something like jq ".locations[] | select(.is_shop and .has_parking_space)"
). Then it will print each filtered item in one single line. Then you can count the lines of the output: jq "your filtering query" | wc -l
Upvotes: 0
Reputation: 36151
If all you want is the number of matching objects, you could efficiently just iterate over the original array, and count on a match (which avoids creating another array that is only used to extract its length).
reduce .locations[] as $loc (0;
if all($loc; has("is_shop", "has_parking_space")) then . + 1 end
)
Note for the use of if
: A missing else
branch defaults to else .
, which was introduced in jq 1.7. Prior to that version, you'd have to spell it out: … then . + 1 else . end
.
Upvotes: 0
Reputation: 26592
Function map
is what you need :
jq '.locations | map(select(has("is_shop") and has("has_parking_space"))) | length' my_locations.json
I think you should use function has
, because you want to test existence
of the keys, not the value.
Upvotes: 4