使用 jq 计算缺少键的记录
Count records with missing keys using jq
下面是调用 API:
时返回的示例输出
curl "https://mywebsite.com/api/cars.json&page=1" | jq '.'
使用 jq
,如何计算缺少 charge
键的记录数?我知道第一段代码将包含 jq '. | length'
但是如何过滤掉包含或不包含某个键值的对象?
如果应用于下面的示例,输出将是 1
{
"current_page": 1,
"items": [
{
"id": 1,
"name": "vehicleA",
"state": "available",
"charge": 100
},
{
"id": 2,
"name": "vehicleB",
"state": "available",
},
{
"id": 3,
"name": "vehicleB",
"state": "available",
"charge": 50
}
]
}
.items | map(select(.charge == null)) | length
这是一个使用 reduce
的更有效的解决方案:
reduce (.items[] | select(.charge == null)) as $i (0;.+=1)
示例 运行(假设 data.json
中的更正 JSON 数据)
$ jq -M 'reduce (.items[] | select(.charge == null)) as $i (0;.+=1)' data.json
1
请注意,假设项目没有 "charge":null
成员,以上每项都采用了一个小的快捷方式。如果某些项目可能有 null
费用,那么 == null
的测试将无法区分这些项目和没有 charge
键的项目。如果这是一个问题,使用 has
的上述过滤器的以下形式更好:
.items | map(select(has("charge")|not)) | length
reduce (.items[] | select(has("charge")|not)) as $i (0;.+=1)
这是一个解决方案,它使用了一个简单但功能强大的实用函数,也许值得您的标准库使用:
def sigma(stream): reduce stream as $s (null; . + $s);
您要使用的过滤器是:
sigma(.items[] | select(has("charge") == false) | 1)
这是非常有效的,因为不需要中间数组,并且不涉及无用的 0 添加。此外,如其他地方所述,使用 has
比对 .charge
.
的值做出假设更可靠
启动文件
如果您不打算使用 jq 的模块系统,您可以简单地将上述 sigma
的定义添加到文件 ~/.jq 并像这样调用 jq:
jq 'sigma(.items[] | select(has("charge") == false) | 1)'
更好的是,如果您还将 def count(s): sigma(s|1);
添加到文件中,调用将只是:
jq 'count(.items[] | select(has("charge") | not))'
标准库
例如,如果 ~/.jq/jq/jq.jq 是您的标准库,那么假设 count/1
包含在此文件中,您可以像这样调用 jq:
jq 'include "jq"; count(.items[] | select(has("charge") == false))'
下面是调用 API:
时返回的示例输出curl "https://mywebsite.com/api/cars.json&page=1" | jq '.'
使用 jq
,如何计算缺少 charge
键的记录数?我知道第一段代码将包含 jq '. | length'
但是如何过滤掉包含或不包含某个键值的对象?
如果应用于下面的示例,输出将是 1
{
"current_page": 1,
"items": [
{
"id": 1,
"name": "vehicleA",
"state": "available",
"charge": 100
},
{
"id": 2,
"name": "vehicleB",
"state": "available",
},
{
"id": 3,
"name": "vehicleB",
"state": "available",
"charge": 50
}
]
}
.items | map(select(.charge == null)) | length
这是一个使用 reduce
的更有效的解决方案:
reduce (.items[] | select(.charge == null)) as $i (0;.+=1)
示例 运行(假设 data.json
中的更正 JSON 数据)
$ jq -M 'reduce (.items[] | select(.charge == null)) as $i (0;.+=1)' data.json
1
请注意,假设项目没有 "charge":null
成员,以上每项都采用了一个小的快捷方式。如果某些项目可能有 null
费用,那么 == null
的测试将无法区分这些项目和没有 charge
键的项目。如果这是一个问题,使用 has
的上述过滤器的以下形式更好:
.items | map(select(has("charge")|not)) | length
reduce (.items[] | select(has("charge")|not)) as $i (0;.+=1)
这是一个解决方案,它使用了一个简单但功能强大的实用函数,也许值得您的标准库使用:
def sigma(stream): reduce stream as $s (null; . + $s);
您要使用的过滤器是:
sigma(.items[] | select(has("charge") == false) | 1)
这是非常有效的,因为不需要中间数组,并且不涉及无用的 0 添加。此外,如其他地方所述,使用 has
比对 .charge
.
启动文件
如果您不打算使用 jq 的模块系统,您可以简单地将上述 sigma
的定义添加到文件 ~/.jq 并像这样调用 jq:
jq 'sigma(.items[] | select(has("charge") == false) | 1)'
更好的是,如果您还将 def count(s): sigma(s|1);
添加到文件中,调用将只是:
jq 'count(.items[] | select(has("charge") | not))'
标准库
例如,如果 ~/.jq/jq/jq.jq 是您的标准库,那么假设 count/1
包含在此文件中,您可以像这样调用 jq:
jq 'include "jq"; count(.items[] | select(has("charge") == false))'