我想在 JQ if 语句中交换两个值。
给定以下 JSON:
{
"food": {
"fruit": [
{
"type": "apple",
"count": 0
},
{
"type": "banana",
"count": 1
},
{
"type": "orange",
"count": 0
}
]
}
}
我想使用 JQ 根据条件交换两个对象的计数以产生以下结果。
{
"food": {
"fruit": [
{
"type": "apple",
"count": 1
},
{
"type": "banana",
"count": 0
},
{
"type": "orange",
"count": 0
}
]
}
}
到目前为止,我可以将第一个水果从 0 改成 1
jq '
if .food.fruit[] | select(.type=="apple") | .count == 0
then
.food.fruit[] | select(.type=="apple") | .count = 1
else
empty
end
'
但我找不到正确的运算符来修改第二个。使用 JQ 是否可以实现类似以下内容?
jq '
if .food.fruit[] | select(.type=="apple") | .count == 0
then
.food.fruit[] | select(.type=="apple") | .count = 1 &
.food.fruit[] | select(.type=="banana") | .count = 0
else
empty
end
'
我无法将其通过管道传输,因为那样会将单个水果对象通过管道传输到下一行,因此我不确定我应该在此处使用哪个运算符 - 如果甚至支持此类功能。 非常感谢任何帮助!
最佳答案
这是一个高效的解决方案,甚至可能不需要完全遍历fruit
数组一次。
想法是找到“apple”和“banana”对象的路径,这样交换就可以在没有任何进一步迭代的情况下完成。
为了提高效率,该解决方案使用 foreach
以便在找到“apple”和“banana”对象的路径后跳出(单个)循环。
.food.fruit |=
( . as $fruits
| label $go
| (foreach paths(objects) as $p ({};
($fruits|getpath($p)) as $x
| if ($x|.type)=="apple"
then .apple = {path: ($p + ["count"]), count: $x.count}
elif ($x|.type) == "banana"
then .banana = {path: ($p + ["count"]), count: $x.count}
else . end;
if .apple and .banana then ., break $go else empty end)
) as $dict
| if $dict | .apple and .banana
then setpath( $dict.apple.path; $dict.banana.count)
| setpath( $dict.banana.path; $dict.apple.count)
else . end
)
定义交换/4
上述解决方案可以抽象如下:
# Input: an array of JSON objects.
#
# In the objects with .[$f1key] == $f1 and .[$f1key] == $f2 if any,
# swap the values at .[$gkey].
# If the the array has more than one object with .[$f1key] == $f1,
# then the last one will be selected, and similarly with respect to $f2
#
def swap($f1; $f2; $fkey; $gkey):
. as $in
| label $go
| (foreach paths(objects) as $p ({};
($in|getpath($p)) as $x
| if ($x[$fkey])==$f1
then .f1 = {path: ($p + [$gkey]), count: $x[$gkey]}
elif ($x[$fkey]) == $f2
then .f2 = {path: ($p + [$gkey]), count: $x[$gkey]}
else . end;
if .f1 and .f2 then ., break $go else empty end)
) as $dict
| if $dict | .f1 and .f2
then setpath( $dict.f1.path; $dict.f2.count)
| setpath( $dict.f2.path; $dict.f1.count)
else . end ;
.food.fruit |= swap("apple"; "banana"; "type"; "count")
关于json - 链接 JQ if : if A then B C else D end,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66260639/