jq:groupby 和嵌套 json 数组
jq: groupby and nested json arrays
假设我有:[[1,2], [3,9], [4,2], [], []]
我想知道要获取的脚本:
are/are非空的嵌套列表数。即想得到:[3,2]
包含或不包含数字3的嵌套列表的个数,即要得到:[1,4]
元素总和is/isn不小于4
的嵌套列表数。即想得到:[3,2]
即嵌套数据分区的基本示例。
由于 whosebug.com 不是编码服务,我将只回答第一个问题,希望它能让您相信学习 jq 是值得的。
让我们首先细化关于列表计数的问题
"which are/are not empty" 强调答案中的第一个数字应对应空列表的数量 (2),第二个数字应对应其余的 (3)。也就是说,要求的答案应该是[2,3]
.
使用 built-in 个过滤器的解决方案
下一步可能是询问是否可以使用group_by
。如果顺序无关紧要,我们可以简单地写:
group_by(length==0) | map(length)
这个returns[3,2]
,这不是我们想要的。现在值得查看有关 group_by
应该做什么的文档。在 https://stedolan.github.io/jq/manual/#Builtinoperatorsandfunctions 查看详细信息时,
我们看到设计 group_by
确实按分组值排序。
因为在 jq,false < true
,我们可以通过写来修复我们的第一次尝试:
group_by(length > 0) | map(length)
很好,但是由于 group_by
做了很多工作,而我们真正需要的只是一种计数方法,很明显我们应该能够想出一个更有效(并且希望不那么不透明)的方法解决方案。
有效的解决方案
问题的核心归结为计数,因此让我们定义一个通用的 tabulate
过滤器来生成不同字符串值的计数。这是满足当前目的的定义:
# Produce a JSON object recording the counts of distinct
# values in the given stream, which is assumed to consist
# solely of strings.
def tabulate(stream):
reduce stream as $s ({}; .[$s] += 1);
现在只需两行就可以写下一个有效的解决方案:
tabulate(.[] | length==0 | tostring )
| [.["true", "false"]]
QED
p.s.
上面名为 tabulate
的函数有时称为 bow
(对于 "bag of words")。在某些方面,这将是一个更好的名称,特别是因为为适用于任意流的类似功能保留名称 tabulate
是有意义的。
假设我有:[[1,2], [3,9], [4,2], [], []]
我想知道要获取的脚本:
are/are非空的嵌套列表数。即想得到:
[3,2]
包含或不包含数字3的嵌套列表的个数,即要得到:
[1,4]
元素总和is/isn不小于
4
的嵌套列表数。即想得到:[3,2]
即嵌套数据分区的基本示例。
由于 whosebug.com 不是编码服务,我将只回答第一个问题,希望它能让您相信学习 jq 是值得的。
让我们首先细化关于列表计数的问题
"which are/are not empty" 强调答案中的第一个数字应对应空列表的数量 (2),第二个数字应对应其余的 (3)。也就是说,要求的答案应该是[2,3]
.
使用 built-in 个过滤器的解决方案
下一步可能是询问是否可以使用group_by
。如果顺序无关紧要,我们可以简单地写:
group_by(length==0) | map(length)
这个returns[3,2]
,这不是我们想要的。现在值得查看有关 group_by
应该做什么的文档。在 https://stedolan.github.io/jq/manual/#Builtinoperatorsandfunctions 查看详细信息时,
我们看到设计 group_by
确实按分组值排序。
因为在 jq,false < true
,我们可以通过写来修复我们的第一次尝试:
group_by(length > 0) | map(length)
很好,但是由于 group_by
做了很多工作,而我们真正需要的只是一种计数方法,很明显我们应该能够想出一个更有效(并且希望不那么不透明)的方法解决方案。
有效的解决方案
问题的核心归结为计数,因此让我们定义一个通用的 tabulate
过滤器来生成不同字符串值的计数。这是满足当前目的的定义:
# Produce a JSON object recording the counts of distinct
# values in the given stream, which is assumed to consist
# solely of strings.
def tabulate(stream):
reduce stream as $s ({}; .[$s] += 1);
现在只需两行就可以写下一个有效的解决方案:
tabulate(.[] | length==0 | tostring )
| [.["true", "false"]]
QED
p.s.
上面名为 tabulate
的函数有时称为 bow
(对于 "bag of words")。在某些方面,这将是一个更好的名称,特别是因为为适用于任意流的类似功能保留名称 tabulate
是有意义的。