如何用jq实现键与数组值反转?解决reduce值覆盖问题
用JQ实现数组值的键值反转(避免值被覆盖)
需求描述
将输入数据中Contents数组的每个唯一元素作为输出对象的键,对应的值是所有包含该元素的原始数据的Id组成的数组。
示例输入
[ { "Id": "abc", "Contents": [ "foo", "bar" ] }, { "Id": "def", "Contents": [ "foo", "baz", "ding" ] }, { "Id": "ghi", "Contents": [ "bar", "dang", "baz" ] } ]
期望输出
{ "foo": [ "abc", "def" ], "bar": [ "abc", "ghi" ], "baz": [ "def", "ghi" ], "ding": [ "def" ], "dang": [ "ghi" ] }
尝试的错误代码
map(.Id as $Id | .Contents | map({key: ., value: [$Id]}) | from_entries ) | reduce .[] as $item ({}; . * $item)
当前错误输出
{ "foo": [ "def" ], "bar": [ "ghi" ], "baz": [ "ghi" ], "ding": [ "def" ], "dang": [ "ghi" ] }
问题原因与解决方案
问题根源
使用*合并对象时,若键重复会直接覆盖旧值,而非合并数组,导致之前的Id被后面的覆盖。
正确JQ代码
reduce .[] as $item ({}; $item.Id as $id | $item.Contents[] as $content | .[$content] += [$id] )
代码说明
- 外层
reduce遍历输入数组的每个元素,初始值为空对象{} - 提取当前元素的
Id存入变量$id - 遍历当前元素
Contents数组的每个内容项$content - 通过
.[$content] += [$id]将$id追加到对应键的数组中:若键不存在则自动创建新数组,存在则直接追加元素
内容的提问来源于stack exchange,提问作者2rs2ts
相关产品推荐
相关产品推荐

