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

luf*_*747 0 command-line json 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}}}
...
Run Code Online (Sandbox Code Playgroud)

我想用JQ告诉我每个测试有多少学生达到> x的分数.

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

{testId: '1' numStudents:1}
{testId: '2' numStudents:2}
{testId: '3' numStudents:0}
Run Code Online (Sandbox Code Playgroud)

我能够生成一份列表,列出了每次考试成绩> 50的学生

{testId, studentId: .studentId[]?} | select(.studentId.score>50)
Run Code Online (Sandbox Code Playgroud)

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

pea*_*eak 5

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

一种方法是使用add:

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

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

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

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

{testId,
 numStudents: ([select(.studentId[].score > 50) ] | length)}
Run Code Online (Sandbox Code Playgroud)

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

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

{testId, numStudents: count(select(.studentId[].score > 50))} 
Run Code Online (Sandbox Code Playgroud)