使用jq v1.6移除同用户名的重复change类型元素并保留原排序
解决jq去重steps数组问题的正确方法
错误原因分析
你之前的命令存在两个核心问题:
.steps[]会把数组拆成单个元素,后续的unique_by无法在数组层面生效,相当于对每个元素单独处理,完全达不到去重效果。- 如果
steps数组里有非对象类型的元素(比如字符串、数字),直接访问.value会触发Cannot index string with string "value"的索引错误。
另外补充:unique_by本身是保留元素第一次出现的实例、剔除后续重复项,是能保留原排序的,但你的写法没用到它的正确场景。
正确命令(两种实现)
实现一:基础版(适合小数据量)
.steps |= reduce .[] as $item ( []; if $item.type == "change" then if (IN($item.value; map(select(.type == "change").value))) then . else . + [$item] end else . + [$item] end )
实现二:高效版(适合大数据量)
用数组记录已出现的value,避免每次遍历结果数组做检查:
.steps |= ( reduce .[] as $item ( { seen: [], result: [] }; if $item.type == "change" then if $item.value | IN($seen[]) then . else .seen += [$item.value] | .result += [$item] end else .result += [$item] end ).result )
命令逻辑说明
两种实现都严格保留原数组顺序,只针对性处理type为"change"的元素:
- 遍历
steps中的每个元素,非"change"类型的元素直接加入结果数组。 - 对于
"change"类型的元素,检查其value是否已经在之前保留的同类型元素中出现过:- 已出现则跳过,不加入结果数组。
- 未出现则加入结果数组,并记录该
value(高效版)。
- 完全兼容数组中的非对象元素,不会触发索引错误。
测试示例
假设输入JSON为:
{ "steps": [ { "type": "change", "value": "root" }, "初始化操作", { "type": "change", "value": "admin" }, { "type": "change", "value": "root" }, { "type": "modify", "value": "root" } ] }
运行命令后输出:
{ "steps": [ { "type": "change", "value": "root" }, "初始化操作", { "type": "change", "value": "admin" }, { "type": "modify", "value": "root" } ] }
可见重复的type="change"且value="root"元素被移除,其他元素的顺序和内容完全保留。
内容的提问来源于stack exchange,提问作者ditku
相关产品推荐
相关产品推荐

