jq是否有独占或(AKA xor)运算符?我在文档中找不到它。
(我很难找到我后来发现在jq中工作的文档中的其他主题,并且有记录。我可能最初没有找到它们,因为我使用的搜索条件很差。)
我希望jq从输入中返回所有顶级对象,这些对象的数组属性包含两个特定值中的一个,但不包含两个值。
例如,给定输入:
[
{"letters": ["a", "c"]},
{"letters": ["a", "b", "c"]},
{"letters": ["b", "c"]}
]
我只想要"letters"
属性包含"a"
或"b"
但不包含两者的对象。
我最终使用了冗长的过滤器:
map(select(.letters//[]|((contains(["a"]) or contains(["b"])) and (contains(["a", "b"])|not))))
给出了正确的输出:
[{"letters":["a","c"]},{"letters":["b","c"]}]
但这是漫长,乏味和维持头痛的问题。有没有更简单的方法来实现这一目标?
此代码的“jq play”代码段:https://jqplay.org/s/mwBhsYud2F
PS:即使没有比我发现的解决方案更好的解决方案,我也很乐意接受有关改进的建设性批评。答案 0 :(得分:0)
这个怎么样:如果data.json
包含你的样本数据命令
$ jq -Mc '
def xor($a;$b): $a != $b ;
map(select(.letters|xor(contains(["a"]);contains(["b"]))))
' data.json
产生
[{"letters":["a","c"]},{"letters":["b","c"]}]
请注意,上面使用的xor
在这里工作,但与非布尔参数一起使用是不安全的。更强大的版本是:
def xor($a;$b): ($a|not) != ($b|not) ;
答案 1 :(得分:0)
如果import okhttp3.FormBody;
中没有重复项,这是另一种利用鲜为人知的数组索引方法的方法:
.letters
产生
$ jq -Mc 'map(select(.letters|.[["a"]]+.[["b"]]|length==1))' data.json
这是有效的,因为如果[{"letters":["a","c"]},{"letters":["b","c"]}]
是数组$x
,则返回$x[ ["a"] ]
中"a"
的索引。 e.g。
$x
另请参阅jq indices builtin(在implementation中使用它)
与一个更明显的方法相比,如果$ jq -Mnc '["a","c"][["a"]]'
[0]
$ jq -Mnc '["a","c"][["b"]]'
[]
$ jq -Mnc '["a","c","a","b"][["a"]]'
[0,2]
包含重复项,那么推荐在一般情况下使用这可能太棘手了,那么简单的.letters
检查将不起作用。
答案 2 :(得分:0)
xor
可以轻松定义:
def xor($a;$b): ($a or $b) and (($a and $b)|not);
contains
很棘手(除非你研究过它的细微之处,否则最好不要使用它)。一般来说,最好使用index
:
.letters | select( xor( index("a"); index("b") ))
为了提高效率,如果你的jq拥有它,那么使用IN
会更好:
.letters as $a | select( xor( "a" | IN($a[]); "b" | IN($a[]) ))