使用jq来计数

Dan*_*ich 8 json count conditional-statements jq

如果我有一个如下所示的 JSON 文件,则使用 jq-1.5

[{... ,"sapm_score":40.776, ...} {..., "spam_score":17.376, ...} ...]
Run Code Online (Sandbox Code Playgroud)

我如何计算其中的数量sapm_score > 40

谢谢,丹

更新:

我查看了输入文件,格式实际上是

{... ,"sapm_score":40.776, ...}
{..., "spam_score":17.376, ...}
...
Run Code Online (Sandbox Code Playgroud)

这会改变人们的计数方式吗?

pea*_*eak 9

[更新:如果输入不是数组,请参阅下面的最后一部分。]

count/1

我建议定义一个count过滤器(也许将其放入 ~/.jq 中),可能如下所示:

 def count(s): reduce s as $_ (0;.+1);
Run Code Online (Sandbox Code Playgroud)

这样,假设输入是一个数组,您可以编写:

 count(.[] | select(.sapm_score > 40))
Run Code Online (Sandbox Code Playgroud)

或者稍微更有效:

 count(.[] | (.sapm_score > 40) // empty)
Run Code Online (Sandbox Code Playgroud)

这种方法(计算流中的项目数)通常优于使用它,length因为它避免了与构造数组相关的成本。

count/2

这是count您可能想要使用的另一个定义(也可能添加到 ~/.jq 中):

def count(stream; cond): count(stream | cond // empty);
Run Code Online (Sandbox Code Playgroud)

这对流中cond既不是false也不是的元素进行计数null

现在,假设输入由数组组成,您可以简单地编写:

count(.[]; .sapm_score > 40)
Run Code Online (Sandbox Code Playgroud)

“sapm_score”与“spam_score”

如果要点是您想要将“sapm_score”规范化为“spam_score”,那么(例如)您可以使用count/2上面定义的方式,如下所示:

 count(.[]; .spam_score > 40 or .sapm_score > 40)
Run Code Online (Sandbox Code Playgroud)

这假设数组中的所有项目都是 JSON 对象。如果情况并非如此,那么您可能需要尝试添加“?” 在键名之后:

count(.[]; .spam_score? > 40 or .sapm_score? > 40)
Run Code Online (Sandbox Code Playgroud)

当然,以上所有内容都假设输入是有效的 JSON。如果情况并非如此,请参阅https://github.com/stedolan/jq/wiki/FAQ#processing-not-quite-valid-json

如果输入是 JSON 对象流...

修改后的问题表明输入由 JSON 对象流组成(而最初输入被认为是 JSON 对象数组)。如果输入由 JSON 对象流组成,则可以轻松调整上述解决方案,具体取决于您拥有的 jq 版本。如果您的 jq 版本有,inputs则建议使用 (2)。

(1) 所有版本:使用-s命令行选项。

(2) 如果你的jq有inputs:使用-n命令行选项,并将.[]上面更改为inputs,例如

count(inputs; .spam_score? > 40 or .sapm_score? > 40)
Run Code Online (Sandbox Code Playgroud)


Jef*_*ado 6

过滤满足条件的项,然后得到长度。

map(select(.sapm_score > 40)) | length
Run Code Online (Sandbox Code Playgroud)