如何在jq中对数组不同部分应用不同函数/映射?
GPS定位JSON数据的jq批量处理问题
需求与现有实现
给定手机GPS定位JSON数据:
{ "latitude": 66.32418638, "longitude": -121.77029769, "altitude": 465.46502685546875, "accuracy": 17.6742248535156, "vertical_accuracy": 36.48805236816406, "bearing": 0.0, "speed": 0.0, "elapsedMs": 55, "provider": "gps" }
需要完成以下处理:
- 提取
latitude、longitude、altitude、accuracy、provider字段 - 对
latitude、longitude保留5位小数 - 对
altitude、accuracy取整 provider保持原样
目前已拆分实现三个独立的jq过滤器:
jq -j '[.latitude,.longitude]|map(.*100000|round/100000)' in.json jq -j '[.altitude,.accuracy]|map(.|round)' in.json jq -j '.provider' in.json
问题与解答
Q1:能否将这些过滤器合并为单个?
可以合并,两种简洁实现方式:
方式1:按字段分组处理
直接针对不同字段应用对应规则后组合成结果:
jq -j '[ (.latitude, .longitude) | (.*100000 | round / 100000), (.altitude, .accuracy) | round, .provider ]' in.json
方式2:统一数组+索引判断
先构造包含所有目标数值字段的数组,结合索引判断应用规则,再追加provider:
jq -j ' [.latitude, .longitude, .altitude, .accuracy] | map( with_index as $idx | if $idx < 2 then .*100000|round/100000 else round end ) + [.provider] ' in.json
Q2:处理大型数组时,能否按索引范围应用不同函数(无需指定属性名)?
完全可以。只要先把待处理元素整理成数组,利用with_index获取元素的索引位置,再通过分支判断对不同索引范围应用对应函数即可。
比如针对大型数组data_array,实现:
- 索引0-1的元素保留5位小数
- 索引2-3的元素取整
- 索引4及以后的元素做自定义处理
代码示例:
jq ' $data_array | map( with_index as $idx | if $idx < 2 then .*100000|round/100000 elif $idx < 4 then round else . * 2 # 自定义其他处理逻辑 end )'
Q3:是否需构建带分支判断的全局map()函数,按索引范围返回对应处理结果?
不需要专门构建全局map函数。jq原生的map配合with_index已经能直接实现按索引分支处理的逻辑,直接在map内部写判断代码即可,简洁直观。
如果需要复用相同的索引处理逻辑,可以封装成自定义函数(可选优化):
jq ' def process_by_index: map( with_index as $idx | if $idx < 2 then .*100000|round/100000 elif $idx < 4 then round else . end ); # 调用示例 [.latitude, .longitude, .altitude, .accuracy] | process_by_index + [.provider] ' in.json
错误代码修正
你之前的代码错误在于误用了index函数——index是用来查找元素在数组中的位置,而非获取当前元素的迭代索引。正确写法应该用with_index绑定当前元素的索引变量:
jq -j '[.latitude,.longitude,.altitude,.accuracy] | map( with_index as $idx | if $idx < 2 then .*100000|round/100000 else round end )' in.json
内容的提问来源于stack exchange,提问作者porte64
相关产品推荐
相关产品推荐

