Reputation: 2572
I have a json structure that looks like:
{
"main":[
{
"0":[ {"0":"..."},{"1":"..."},{"2":"..."},{"3":"..."} ]
},
{
"1":[ {"0":"..."},{"1":"..."},{"2":"..."} ]
},
{
"2":[ {"0":"..."},{"1":"..."},{"2":"..."},{"3":"..."},{"4":"..."} ]
}
]
}
What I would like is to be able to count the total number of elements within each direct child of "main"
. For example, in the above, "main"
has an array containing 3 direct childs, "0", "1", "2"
. For "0"
, we have 4 such elements, "1"
we have 3 such elements, and "2"
we have 5 such elements.
Is there a way to use jq
to return 12
as the final answer for the above?
Upvotes: 0
Views: 1648
Reputation: 265648
Double map + length + add:
.main|map(map(length)|add)|add
Or
.main|map(map(length))|add|add
Or stream all values first, wrap in array and get array length (this is probably the sexiest shortest, but not very memory-efficient):
[.main[][][]]|length
If memory is an issue or you have a huge number of elements, use reduce
as suggested by @peak in another answer
Upvotes: 1
Reputation: 116919
It might not matter in many cases, but constructing arrays just for the sake of counting is inefficient. In any case, it’s nice to have the following stream-oriented def in your quiver:
def count(s): reduce s as $_ (0; .+1);
With that, you can e.g. write:
count(.main[][][])
Upvotes: 1
Reputation: 36326
You could count all scalars in the document:
jq '[..|scalars] | length'
If you just want to consider the tree under .main
, prepend it:
jq '.main | [..|scalars] | length'
If there's many elements and you don't want to buid up an intermediate array, only needed to take its length from, count on the fly using reduce
:
jq 'reduce (..|scalars) as $_ (0; .+1)'
Upvotes: 2
Reputation: 50795
This produces 12 for your sample input:
[.main[][] | length] | add
Upvotes: 1