Given an input json string of keys from an array, return an object with only the entries that had keys in the original object and in the input array.
I have a solution but I think that it isn't elegant ({($k):$input[$k]}
feels especially clunky...) and that this is a chance for me to learn.
jq -n '{"1":"a","2":"b","3":"c"}' \
| jq --arg keys '["1","3","4"]' \
'. as $input
| ( $keys | fromjson )
| map( . as $k
| $input
| select(has($k))
| {($k):$input[$k]}
)
| add'
Any ideas how to clean this up?
I feel like Extracting selected properties from a nested JSON object with jq is a good starting place but i cannot get it to work.
solution with inside check:
the inside operator works for most of time; however, I just found the inside operator has side effect, sometimes it selected keys not desired, suppose input is
{ "key1": val1, "key2": val2, "key12": val12 }
and select byinside(["key12"])
it will select both"key1"
and"key12"
use the in operator if need an exact match: like this will select
.key2
and.key12
onlybecause the in operator checks key from an object only (or index
exists?
from an array), here it has to be written in an object syntax, with desired keys as keys, but values do not matter; the use of in operator is not a perfect one for this purpose, I would like to see the Javascript ES6 includes API's reverse version to be implemented as jq builtinhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
to check an item
.key
isincluded?
from an arrayHere is some additional clarification
For the input object
{"key1":1, "key2":2, "key3":3}
I would like to drop all keys that are not in the set of desired keys["key1","key3","key4"]
with_entries
converts{"key1":1, "key2":2, "key3":3}
into the following array of key value pairs and maps the select statement on the array and then turns the resulting array back into an object.Here is the inner object in the
with_entries
statement.we can then select the keys from this array that meet our criteria.
This is where the magic happens... here is a look at whats going on in the middle of this command. The following command takes the expanded array of values and turns them into a list of objects that we can select from.
This will yield the following result
The with entries command can be a little tricky but its easy to remember that it takes a filter and is defined as follows
This is the same as
The other part of the question that confuses people is the multiple matches on the right hand side of the
==
Consider the following command. We see the output is an outer production of all the left hand lists and the right hand lists.
If that predicate is in a select statement, we keep the input when the predicate is true. Note you can duplicate the inputs here too.
You can use this filter:
Jeff's answer has a couple of unnecessary inefficiencies, both of which are addressed by the following, on the assumption that
--argjson keys
is used instead of--arg keys
: