使用jq我們可以輕松地合并兩個多級物件 X 和 Y 使用*:
X='{
"a": 1,
"b": 5,
"c": {
"a": 3
}
}' Y='{
"d": 2,
"a": 3,
"c": {
"x": 10,
"y": 11
}
}' && Z=`echo "[$X,$Y]"|jq '.[0] * .[1]'` && echo "Z='$Z'"
給我們:
Z='{
"a": 3,
"b": 5,
"c": {
"a": 3,
"x": 10,
"y": 11
},
"d": 2
}'
但就我而言,我從 X 和 Z 開始并想計算 Y(例如 X * Y = Z)。如果我們只有具有標量屬性的物件,則jq X Y等于Z,我們也可以計算Y為jq Z - X。但是,如果 X 或 Y 包含具有物件值的屬性,則此操作將失敗,例如在上面的示例中:
X='{
"a": 1,
"b": 5,
"c": {
"a": 3
}
}' Z='{
"a": 3,
"b": 5,
"c": {
"a": 3,
"x": 10,
"y": 11
},
"d": 2
}' && echo "[$X,$Z]" | jq '.[1] - .[0]'
拋出錯誤 jq: error (at <stdin>:16): object ({"a":3,"b":...) and object ({"a":1,"b":...) cannot be subtracted
jq 是否有優雅的解決方案來解決這個問題?
uj5u.com熱心網友回復:
我不知道這是否優雅,但它適用于您的示例資料
echo "[$X,$Z]" | jq '
. as [$x,$z]
| map([paths(scalars)])
| .[0] |= map(select(. as $p | [$x, $z | getpath($p)] | .[1] == .[0]))
| reduce (.[1] - .[0])[] as $p ({}; setpath($p; $z | getpath($p)))
'
{
"a": 3,
"c": {
"x": 10,
"y": 11
},
"d": 2
}
演示
uj5u.com熱心網友回復:
def remove($o2):
reduce ( to_entries[] | [ .key, .value ] ) as [ $k, $v1 ] (
{};
if $o2 | has($k) | not then
# Keep existing value if $o2 doesn't have the key.
.[$k] = $v1
else
$o2[$k] as $v2 |
if $v1 | type == "object" then
# We're comparing objects.
( $v1 | remove($o2[$k]) ) as $v_diff |
if $v_diff | length == 0 then
# Discard identical values.
.
else
# Keep the differences of the values.
.[$k] = $v_diff
end
else
# We're comparing non-objects.
if $v1 == $v2 then
# Discard identical values.
.
else
# Keep existing value if different.
.[$k] = $v1
end
end
end
);
. as [ $Z, $X ] | $Z | remove($X)
jqplay 上的演示
或者
def sub($v2):
( type ) as $t1 |
( $v2 | type ) as $t2 |
if $t1 == $t2 then
if $t1 == "object" then
with_entries(
.key as $k |
.value = (
.value |
if $v2 | has($k) then sub( $v2[$k] ) else . end
)
) |
select( length != 0 )
else
select( . != $v2 )
end
else
.
end;
. as [ $Z, $X ] | $Z | sub($X)
jqplay 上的演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/404622.html
標籤:
