Reputation: 894
The following example from the jq docs worked as expected --
$ echo '[1,2]' | jq 'map(in([0,1]))'
[
true,
false
]
but making the values into strings failed -
$ echo '["1", "2"]' | jq 'map(in(["0","1"]))'
jq: error (at <stdin>:1): Cannot check whether array has a string key
To make sure that this wasn't a shell-quoting issue, I also tried --
$ echo "[\"1\", \"2\"]" | jq 'map(in(["0","1"]))'
jq: error (at <stdin>:1): Cannot check whether array has a string key
To add to this, the following snippet also fails, which is probably due to a casting of 0 into the boolean false -
$ echo '[0,1]' | jq 'map(in([1,2]))'
[
true,
true
]
Upvotes: 1
Views: 935
Reputation: 491
actually inside does seem to do the trick (apparently added in v1.5)
jq -n '[123,444,565,344,"333",111,1111,87] | map([.]|inside([111,333,344]))'
produces
[
false,
false,
false,
true,
false,
true,
false,
false
]
Upvotes: 0
Reputation: 116957
index/1
is the builtin that can most conveniently be used for checking array membership. Although it is not strictly boolean, the semantics of if
and //
make it convenient to use as though it were. If you want a strictly boolean test, then simply use the idiom index(_) != null
.
index/1
is worth understanding in detail, so consider reviewing the jq manual and FAQ accordingly. Note also that INDEX/1
is no relation.
Upvotes: 2
Reputation: 134571
You're misunderstanding what in/1
is doing. It's not testing whether a value is a member of the array, but rather if the value is a member of the object's keys. So for arrays, numbers are expected (the indices) or for objects, strings (the keys). It's exactly the same as has/1
but the inputs are swapped.
$ jq -n '[0,-1,20,9,16,10] | map(in([range(20;30)]))' # 10 item array
[
true,
false,
false,
true,
false,
false
]
$ jq -n '["foo","bar"] | map(in({foo:1,boo:2,bat:3}))'
[
true,
false
]
If you wanted to test membership in the array, there isn't a builtin but you could craft it yourself. Though contains/1
is close but not quite since it tests if strings are substrings and not equal. any/2
could be used to do this.
def has_value($value):
any(.[]; . == $value);
def in_array($arr): # swapped input version
. as $value | any($arr[]; . == $value);
Upvotes: 6