Leevi L
Leevi L

Reputation: 1789

How to use jq to return length of filtered array?

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

Answers (3)

Accident2ly
Accident2ly

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

pmf
pmf

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

Philippe
Philippe

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

Related Questions