jq:计算满足条件的嵌套对象值

时间:2016-10-19 00:50:59

标签: json command-line count jq

json数据:

{testId: '1' studentId:{'s1':{score: 20} 's2':{score: 80}}}
{testId: '2' studentId:{'s1':{score: 60} 's2':{score: 70}}}
{testId: '3' studentId:{'s5':{score: 40} 's7':{score: 30}}}
...

我想用JQ告诉我有多少学生获得了分数> x,每次测试。

因此对于上面的输入和x = 50,输出:

{testId: '1' numStudents:1}
{testId: '2' numStudents:2}
{testId: '3' numStudents:0}

我能够生成所有达到>的学生的列表。

每次测试50次
{testId, studentId: .studentId[]?} | select(.studentId.score>50)

此命令创建一个对象列表,其中每个对象包含testId,studentId和score,其中所有分数都大于50.但我不知道如何将这些结果重新组合到我想要的输出中。

1 个答案:

答案 0 :(得分:5)

以下假设输入包含有效JSON对象流。

一种方法是使用add

$ jq '{testId, numStudents: ([select(.studentId[].score > 50) | 1] | add // 0)}' 

使用给定的输入(在进行了更正之后),输出将是:

{ "testId": "1", "numStudents": 1 } { "testId": "2", "numStudents": 2 } { "testId": "3", "numStudents": 0 }

另一种方法是使用length,例如使用此过滤器:

{testId,
 numStudents: ([select(.studentId[].score > 50) ] | length)}

但是,如果您不介意添加' def'那么最佳解决方案(例如,因为它不涉及构建中间数组)将沿着以下几行:

def count(s): reduce s as $i (0; .+1);

{testId, numStudents: count(select(.studentId[].score > 50))}