使用jq对嵌套数组按同字符串分组求和,是否有更简洁写法?
问题说明
现有存储键值对的二维嵌套数组,结构示例如下:
[ ["stringA", 1], ["stringA", 2], ["stringB", 3], ["stringB", 4], ["stringC", 5], ["stringC", 6] ]
需要实现的逻辑:将首元素(字符串key)相同的子数组的第二项数值累加,最终输出同结构的分组求和结果,预期输出如下:
[ ["stringA", 3], ["stringB", 7], ["stringC", 11] ]
当前可实现需求的jq代码如下,希望找到更简洁、性能更优的写法:
group_by(.[0]) | .[] |= [.[0][0], ([.[][1]] | add)]
优化实现方案
以下是几种不同场景下的更优写法:
写法1:逻辑更简洁的group_by简化版
把原写法中的原地更新运算符|=替换为map,减少不必要的路径引用,可读性更高:group_by(.[0]) | map([first[0], map(.[1]) | add])逻辑说明:先按子数组首项分组,之后遍历每个分组,直接取分组第一个元素的首项作为结果key,提取分组内所有子数组的第二项求和作为value,拼接成目标子数组。
写法2:保序高性能的reduce版本
group_by底层会先对全量数据做排序,输出结果默认按key字典序排列,如果需要保持key在原数组中首次出现的顺序,或是处理超大数组追求更高性能,可以用reduce逐行累加,省去排序开销:reduce .[] as [$k, $v] ({}; .[$k] += $v) | to_entries | map([.key, .value])逻辑说明:遍历原数组每一项,把键值对累加到临时对象中,最后把对象转成键值对数组,再调整为目标二维数组结构即可。
内容的提问来源于stack exchange,提问作者user3166580
相关产品推荐
相关产品推荐

