jq:从对象中选择键的子集
jq: selecting a subset of keys from an object
给定一个数组中的 json 键字符串输入,return 一个对象,该对象仅包含在原始对象和输入数组中具有键的条目。
我有一个解决方案,但我认为它不够优雅({($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'
有什么办法可以清理吗?
我觉得 是一个很好的起点,但我无法让它发挥作用。
您可以使用这个过滤器:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
这里有一些补充说明
对于输入对象 {"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
}
]
然后我们可以 select 这个数组中满足我们条件的键。
这就是奇迹发生的地方...这里是这个命令中间发生的事情。以下命令获取扩展的值数组并将它们转换为我们可以 select 来自的对象列表。
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
Jeff 的回答有几个不必要的低效问题,假设使用 --argjson keys
而不是 --arg keys
:
with_entries( select( .key as $k | $keys | index($k) ) )
内部检查解决方案:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
内部操作员大部分时间都在工作;然而,我刚刚发现内部运算符有副作用,有时它 selected 键不需要,假设输入是 { "key1": val1, "key2": val2, "key12": val12 }
和 select by inside(["key12"])
它会 select "key1"
和 "key12"
如果需要精确匹配,请使用 in 运算符:像这样只会 select .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?
给定一个数组中的 json 键字符串输入,return 一个对象,该对象仅包含在原始对象和输入数组中具有键的条目。
我有一个解决方案,但我认为它不够优雅({($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'
有什么办法可以清理吗?
我觉得
您可以使用这个过滤器:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
这里有一些补充说明
对于输入对象 {"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
}
]
然后我们可以 select 这个数组中满足我们条件的键。
这就是奇迹发生的地方...这里是这个命令中间发生的事情。以下命令获取扩展的值数组并将它们转换为我们可以 select 来自的对象列表。
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
Jeff 的回答有几个不必要的低效问题,假设使用 --argjson keys
而不是 --arg keys
:
with_entries( select( .key as $k | $keys | index($k) ) )
内部检查解决方案:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
内部操作员大部分时间都在工作;然而,我刚刚发现内部运算符有副作用,有时它 selected 键不需要,假设输入是 { "key1": val1, "key2": val2, "key12": val12 }
和 select by inside(["key12"])
它会 select "key1"
和 "key12"
如果需要精确匹配,请使用 in 运算符:像这样只会 select .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?