更新符合不好路径下条件的字段。

huangapple go评论57阅读模式
英文:

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 someValues:

.very."un-fortunate"."p-a-t-h"[].someValue |= . + 10

or

.very."un-fortunate"."p-a-t-h"[].someValue += 10

To update only someValues 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

huangapple
  • 本文由 发表于 2023年2月27日 17:12:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75578551.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定