如何用jq表达式通过中间映射数组获取product1关联的颜色名称?
问题:使用jq获取与product1关联的颜色名称
给定JSON数据:
{ "links": [ { "from": "product1", "to": "color1" }, { "from": "product1", "to": "color2" }, { "from": "product2", "to": "color3" } ], "hits": [ { "id": "color1", "name": "green" }, { "id": "color2", "name": "blue" }, { "id": "color3", "name": "yellow" } ] }
需要获取与product1关联的颜色名称(预期结果:["green", "blue"])。
已写出硬编码的jq表达式:
[.links[] | select(.from == "product1") | .to] as $colors | [.hits[] | select(.id == ("color1","color2")) | .name]
但希望用$colors变量代替硬编码的("color1","color2"),尝试以下表达式时得到空数组:
[.links[] | select(.from == "product1") | .to] as $colors | [.hits[] | select(.id == ($colors)) | .name]
解决方案
问题原因
$colors是一个数组(["color1","color2"]),直接用.id == $colors是将单个字符串(比如color1)和整个数组比较,永远不相等,因此返回空数组。需要判断.id是否存在于$colors数组中。
方法1:使用IN运算符判断成员关系
IN可以检查值是否在给定的集合中,结合数组展开$colors[]即可实现判断:
[.links[] | select(.from == "product1") | .to] as $colors | [.hits[] | select(.id | IN($colors[])) | .name]
方法2:使用index检查数组中是否存在目标值
$colors | index(.id)会返回目标值在数组中的索引,若存在则为非空值,可作为判断条件:
[.links[] | select(.from == "product1") | .to] as $colors | [.hits[] | select($colors | index(.id)) | .name]
方法3:先构建颜色映射表(更高效)
先将hits转换为id: name的键值对映射,再直接通过to字段查找对应名称,适合数据量较大的场景:
.hits | map({(.id): .name}) | add as $colorMap | [.links[] | select(.from == "product1") | .to | $colorMap[.]]
上述三种方法均可得到预期结果["green", "blue"]。
内容的提问来源于stack exchange,提问作者Antônio
相关产品推荐
相关产品推荐

