英文:
updating fields matching condition under not nice path
问题
我需要经常有条件地更新子树中的某些字段,而这些子树的路径看起来很不美观。我有一种解决方法,但它非常丑陋,我想知道是否有更好的方法。
示例输入:
{
"very": {
"un-fortunate": {
"p-a-t-h": {
"first": {
"veryDeepSubTree": {},
"someValue": 1
},
"second": {
"veryDeepSubTree": {},
"someValue": 2
},
"third": {
"veryDeepSubTree": {},
"someValue": 3
}
}
}
}
}
期望的输出:假设我想将10添加到 someValue。假设我不能使用递归下降,例如,我只想更新奇数 someValue。
我可以编写以下解决方案:
jq '.very|=(.["un-fortunate"]|=(.["p-a-t-h"] |=( . as $root| reduce keys[] as $k ({}; . + {($k): ($root|.[$k]|.someValue|=(.+10))}) )))'
但这很难阅读和编写(匹配括号)...
根据我的(误解?)理解的解释:
- 如果我理解正确,我需要给 |= 的每个非平凡右操作数加括号,特别是如果有多个右操作数,否则它无法编译。
- 如果路径足够复杂,我无法一次性表示更长的路径。
- 除了使用 reduce 复制所有内容到新的更新值并在 reduce 命令的更新子句中更新每个部分外,没有其他方法(也许除了 foreach,但我无法理解)来更新对象的所有项目。
问题:
- 有没有更好的方式来表示从树根到不幸路径?
- 有没有更简单的方式来表示它,而不是通过使用 reduce 遍历键,将字段更新逻辑放入 reduce 命令的累加器部分?
- 如果您将命令写入 shell,如何才能轻松编辑它并使其易于阅读?
英文:
I need very often update conditionally some fields in subtree to which leads ugly path. I kinda can solve it, but it's very ugly solution, I'd like to know if there is smth better.
Sample input:
{
"very": {
"un-fortunate": {
"p-a-t-h": {
"first": {
"veryDeepSubTree": {},
"someValue": 1
},
"second": {
"veryDeepSubTree": {},
"someValue": 2
},
"third": {
"veryDeepSubTree": {},
"someValue": 3
}
}
}
}
}
desired output: say that I would like to add 10 to someValue. Suppose that I cannot use recursive descent, for example I want to update only odd someValue.
I can write solution like this:
jq '.very|=(.["un-fortunate"]|=(.["p-a-t-h"] |=( . as $root| reduce keys[] as $k ({}; . + {($k): ($root|.[$k]|.someValue|=(.+10))}) )))'
but it's hard to read and write (matching brackets)...
explained motivation, based on my (mis?)understanding:
- iiuc I need to bracket every non-trivial right operand of |= , especially if there are more of them, otherwise it does not compile
- I cannot express longer path than just one field at a time, if path is sufficiently ugly
- there isn't other way(maybe except foreach, which I cannot understand) to update all items of object, than using reduce to copy all into new updating value, and update each part in update clause of reduce command
questions:
- is there some better way of expressing unfortunate path from tree root?
- can I express it somehow easier than via using this reduce over keys, and putting field update logic into accumulator part of reduce command?
- if you are writing commands into shell, how do you do it so that you can easily edit it + it's readable?
答案1
得分: 1
你可以使用array value iterator []
与(arithmetic) update-assignment operator |=
结合使用。
要更新所有 someValue
:
.very."un-fortunate"."p-a-t-h"[].someValue |= . + 10
或者
.very."un-fortunate"."p-a-t-h"[].someValue += 10
要仅更新奇数的 someValue
,通过select
进行筛选,并不要忘记将左侧括起来:
(.very."un-fortunate"."p-a-t-h"[].someValue | select(. % 2 != 0)) += 10
输出:
{
"very": {
"un-fortunate": {
"p-a-t-h": {
"first": {
"veryDeepSubTree": {},
"someValue": 11
},
"second": {
"veryDeepSubTree": {},
"someValue": 2
},
"third": {
"veryDeepSubTree": {},
"someValue": 13
}
}
}
}
}
但即使是递归下降也可以工作,只需确保仅选择正确的值:
(.. | objects | .someValue | values | select(. % 2 != 0)) += 10
或者
(.. | .someValue? | values | select(. % 2 != 0)) += 10
输出与上述相同。
英文:
You could use the array value iterator []
in combination with the (arithmetic) update-assignment operator |=
.
To update all someValue
s:
.very."un-fortunate"."p-a-t-h"[].someValue |= . + 10
or
.very."un-fortunate"."p-a-t-h"[].someValue += 10
To update only someValue
s which are odd, filter through select
and don't forget to parenthesize the LHS):
(.very."un-fortunate"."p-a-t-h"[].someValue | select(. % 2 != 0)) += 10
Output:
{
"very": {
"un-fortunate": {
"p-a-t-h": {
"first": {
"veryDeepSubTree": {},
"someValue": 11
},
"second": {
"veryDeepSubTree": {},
"someValue": 2
},
"third": {
"veryDeepSubTree": {},
"someValue": 13
}
}
}
}
}
But even recursive descent would work, you just have to make sure to only select the correct values:
(.. | objects | .someValue | values | select(. % 2 != 0)) += 10
or
(.. | .someValue? | values | select(. % 2 != 0)) += 10
Output is identical to above.
答案2
得分: 0
以下是翻译好的部分:
The following approach using walk
is worth knowing about:
使用 walk
的以下方法值得了解:
walk(if try (.someValue % 2 != 0) catch false then .somevalue += 10 else . end)
通过更少的按键:
使用更少的按键:
walk(if (.someValue% 2 != 0)? // null then .somevalue += 10 else . end)
或者更有针对性一些:
或者更加有针对性一些:
(try (.[][][][].someValue) | select(. % 2 != 0)) += 10
英文:
The following approach using walk
is worth knowing about:
walk(if try (.someValue % 2 != 0) catch false then .somevalue += 10 else . end)
Or with fewer keystrokes:
walk(if (.someValue% 2 != 0)? // null then .somevalue += 10 else . end)
Or a bit more targeted:
(try (.[][][][].someValue) | select(. % 2 != 0)) += 10
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论