问题
I'm trying to filter lists using contains
function, provided by jq. My input,
[1, 2, 3, 4, 5]
And I have a "whitelist":
[3, 4, 7]
I need to filter input list through whitelist. Expected output:
[3, 4]
I'm able to filter comparing a single item:
jq --compact-output --null-input '[1,2,3,4,5] | map(select(. | contains(3)))'
[3]
I tried this:
$ jq --compact-output --null-input '[1,2,3,4,5] | map(select([3,4,7] | contains([.])))'
[]
$
Here [3,4,7] | contains([.])
intents to pose question:
is
[.]
a sublist of list[3,4,7]
?
But it doesn't work. What am I missing?
How do I filter using a whitelist?
回答1:
The filter you'd use with contains
is:
map(. as $x | select([3,4,7] | contains([$x])))
Your attempt uses . incorrectly.
Using index/1
For this type of problem, it might be better to use index/1
than contains
or its inverse, inside
. The reasons stem from both semantic and efficiency considerations.
If the whitelist is available as $whitelist and if you want to use map(select(...)), an appropriate filter would be:
map( . as $x | select($whitelist|index($x)))
For long arrays, this of course is very inefficient. For such arrays, you will almost surely want to look at alternatives, such as using bsearch
(binary search), or a JSON object (hash).
def ix:
The current implementation of index/1
is less than ideal for the present purpose, but it is fast because it is written in C. Here's an alternative definition that assumes the availability of any/2
:
def ix(x): any(.[]; .==x);
回答2:
Changed contains
for inside
and it seems to work now:
$ jq --compact-output --null-input '[1,2,3,4,5] | map(select([.] | inside([3,4,7])))'
[3,4]
$
来源:https://stackoverflow.com/questions/43833974/whitelisting-objects-using-select