在jq
中,如何添加嵌套在流对象中的数字?
示例:
{"game":
{"player1": {"score": 2}}}
{"game":
{"player1": {"score": 4}}}
我可以使用两个jq
呼叫添加这些数字:
$ cat foo.json | jq '.game.player1.score' | jq --slurp 'add'
6
如何通过一个jq
呼叫来完成?
而且,如何分别增加两个不同玩家的得分?
{"game":
{"player1": {"score": 2},
"player2": {"score": 20}}}
{"game":
{"player1": {"score": 4},
"player2": {"score": 40}}}
$ cat foo.json | jq '???'
{"player1": 6, "player2": 60}
[首先,这是@OguzIsmail针对第一个问题的第一个解决方案的变体。它用于验证通用函数的有效性:
def sigma(s): reduce s as $x (0; .+$x);
有了这个,并使用-n命令行选项,给定问题的解决方案很简单:
sigma(inputs.game.player1.score)
具有相同的通用性:
def sigmas(stream; f):
reduce stream as $s (null;
[., ($s | f)] | transpose | map(add));
sigmas(inputs | .game; [.player1.score, .player2.score])
| {player1: .[0], player2: .[1]}
注意,此处定义的sigmas
可以任意处理许多求幂。对于读者来说,这是一个更简单的练习,它避免了将求知数指定为列表的需要,这是更简单的练习:-)
通常,通用函数可以包含在“标准jq库”中。例如,如果您的实用程序函数位于〜/ .jq / jq.jq中,则假定pwd没有不同的jq.jq,则可以编写(针对第一个问题的解决方案):
jq -n 'include "jq"; sigma(inputs.game.player1.score)' foo.json
为了避免与模块路径相关的困难,有时在include
或import
指令中指定路径是有意义的,例如:
jq -n 'include "jq" {search: "~/jq"}; ...'
一个选项是使用reduce
,例如:
jq -n 'reduce inputs.game.player1.score as $score (0; . + $score)' file
另一个是:
jq -n '[inputs.game.player1.score] | add' file
但是这在输入较大时效果不如第一个。
这也是一个涵盖第二个Q的更通用的一个>>
jq -n 'reduce inputs.game as $game ({};
reduce ($game|keys_unsorted)[] as $player (.;
.[$player] += $game[$player].score
)
)' file
这是从对象流定义表(即电子表格)的角度提出的通用解决方案。该解决方案也是有效的(无拖延)和稳健的(无关于键的顺序或存在的假设)。
这是一个具有帮助功能的解决方案,它使用