如何使用JQ统计数组唯一值计数并按指定结构重构JSON
JQ实现数组唯一值计数(类
sort | uniq -c)方案 直接用jq内置的分组函数就能实现,不需要写复杂的循环赋值逻辑,处理时不会破坏原有需要保留的字段,完整命令如下:
jq 'map( # 过滤空值、分组统计fruit数组元素出现次数,提前构造metadata结构 (.fruit | map(select(. != "")) | group_by(.) | map({ name: "fruit", value: "\(.[0]) - \(length)" })) as $metadata # 构造返回对象:保留uid、tID字段,移除原fruit,挂载统计结果 | {uid, tID, metadata: $metadata} )' 你的输入文件路径.json
逻辑说明
- 外层
map()负责逐一遍历输入数组中的每个顶层对象,单独处理 - 统计逻辑段:
- 先取出当前对象的
fruit数组,用select(. != "")过滤掉所有空字符串,不纳入计数 - 调用
group_by(.)对相同值的元素做分组,相同值会被归入同一个子数组,自带排序效果,和shell中sort | uniq的前置逻辑一致 - 分组后遍历每个子数组,直接拼接成metadata要求的结构:
name固定为"fruit",value通过字符串插值拼成「元素值 - 出现次数」的格式,其中子数组的第一个元素就是当前分组的元素值,子数组长度就是该值的出现次数
- 先取出当前对象的
- 用
as $metadata把统计结果暂存为临时变量,最后用jq的对象简写语法{uid, tID, metadata: $metadata}直接构造返回对象:会自动把原对象的uid、tID字段原封不动保留,自动丢弃原fruit字段,新增metadata字段挂载统计结果,完全不会改动原有保留字段的内容。
可选调整
如果需要调整统计结果的排序规则,比如按出现次数降序排列,只要在分组后加排序逻辑即可:
(.fruit | map(select(. != "")) | group_by(.) | sort_by(-length) | map({ name: "fruit", value: "\(.[0]) - \(length)" })) as $metadata
内容的提问来源于stack exchange,提问作者user2480552
相关产品推荐
相关产品推荐

