user321627
user321627

Reputation: 2572

How to use jq to count all instances of a field that is nested numerically in an array?

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

Answers (4)

knittl
knittl

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

peak
peak

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

pmf
pmf

Reputation: 36326

You could count all scalars in the document:

jq '[..|scalars] | length'

Demo

If you just want to consider the tree under .main, prepend it:

jq '.main | [..|scalars] | length'

Demo

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)'

Demo

Upvotes: 2

oguz ismail
oguz ismail

Reputation: 50795

This produces 12 for your sample input:

[.main[][] | length] | add

Online demo

Upvotes: 1

Related Questions