给定一个来自数组的键的输入json字符串,返回一个只包含原始对象和输入数组中键的条目的对象。
我有一个解决方案,但我认为它并不优雅({($k):$input[$k]}
感觉特别笨重...)而且这是我学习的机会。
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'
有任何想法如何清理它?
我觉得Extracting selected properties from a nested JSON object with jq是一个很好的起点,但我无法让它发挥作用。
答案 0 :(得分:8)
您可以使用此过滤器:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
答案 1 :(得分:4)
内部检查解决方案:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
答案 2 :(得分:1)
杰夫的回答有一些不必要的低效率,假设使用--argjson keys
代替--arg keys
,这两个问题都由以下问题解决:
with_entries( select( .key as $k | $keys | index($k) ) )
答案 3 :(得分:1)
内部操作员大部分时间都在工作;但是,我发现内部运算符有副作用,有时它选择了不需要的键,假设输入为{ "key1": val1, "key2": val2, "key12": val12 }
并由inside(["key12"])
选择,它将同时选择"key1"
和"key12"
如果需要完全匹配,请使用in运算符:这样只会选择.key2
和.key12
jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
因为in运算符只检查来自对象的键(或从数组中索引exists?
),所以它必须用对象语法编写,所需的键作为键,但值无关紧要;使用in运算符不是一个完美的用于此目的,我希望看到Javascript ES6包含API的反向版本实现为jq builtin
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
jq 'with_entries(select(.key | included(["key2", "key12"])))'
从数组
检查项.key
是included?
答案 4 :(得分:0)
这是一些额外的澄清
对于输入对象{"key1":1, "key2":2, "key3":3}
,我想删除不在所需键集["key1","key3","key4"]
jq -n --argjson desired_keys '["key1","key3","key4"]' \
--argjson input '{"key1":1, "key2":2, "key3":3}' \
' $input
| with_entries(
select(
.key == ($desired_keys[])
)
)'
with_entries
将{"key1":1, "key2":2, "key3":3}
转换为以下键值对数组,并将select语句映射到数组上,然后将生成的数组转换回对象。
这是with_entries
语句中的内部对象。
[
{
"key": "key1",
"value": 1
},
{
"key": "key2",
"value": 2
},
{
"key": "key3",
"value": 3
}
]
然后我们可以从这个数组中选择符合我们标准的键。
这就是魔术发生的地方......这里是看看这个命令中间发生了什么。以下命令获取扩展的值数组,并将它们转换为我们可以选择的对象列表。
jq -cn '{"key":"key1","value":1}, {"key":"key2","value":2}, {"key":"key3","value":3}
| select(.key == ("key1", "key3", "key4"))'
这将产生以下结果
{"key":"key1","value":1}
{"key":"key3","value":3}
with entries命令可能有点棘手,但很容易记住它需要一个过滤器并定义如下
def with_entries(f): to_entries|map(f)|from_entries;
这与
相同def with_entries(f): [to_entries[] | f] | from_entries;
令人困惑的问题的另一部分是==
请考虑以下命令。我们看到输出是所有左手列表和右手列表的外部产生。
jq -cn '1,2,3| . == (1,1,3)'
true
true
false
false
false
false
false
false
true
如果该谓词在select语句中,我们在谓词为真时保留输入。请注意,您也可以在这里复制输入。
jq -cn '1,2,3| select(. == (1,1,3))'
1
1
3