jq:groupby 和嵌套 json 数组

jq: groupby and nested json arrays

假设我有:[[1,2], [3,9], [4,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 是有意义的。