how to check if all elements are equal with jq

Viewed 1232

I have json data from curl like this:

[
   {
     "state": "foo",
   },
   {
     "state": "foo",
   },
   {
     "state": "foo",
   }
]

output of curl uri | jq .[].state would be

"foo"
"foo"
"foo"

How can I check with jq if all the "state" values are equal and use this true or false status next in my condition? in this example I would get true value.

but here

"foo"
"foo"
"bar"

should be false

3 Answers

It would be easy to come up with an inefficient solution, e.g. using map or unique, but it's also quite easy to use all/2 to devise an efficient, generic solution.

Consider the following stream-oriented function:

# Return `true` if s is the empty stream
def allEquals(s):
  (first(s) // null) as $x | all(s; .==$x);

Using this, we can efficiently test for the equality of all the .state values in an array of objects as in the sample data, while ignoring other keys:

allEquals(.[].state)

Footnote

Of course, if the objects in the array have only one key, as in the sample shown in the Q, one could simply write:

.[0] as $x | all(.[]; . == $x)

Thanks to jq's neat handling of edge cases, this works even if the input array is empty.

this code [.[].state == ("foo") ] | all works as expected

Related