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

jq: count nest object values which satisfy condition

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 和分数,其中所有分数都大于 50。但是我不知道如何将这些结果重新组合成我想要的输出。

以下假定输入由有效 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))}