【问题标题】:jq - How to select objects based on a 'whitelist' of property valuesjq - 如何根据属性值的“白名单”选择对象
【发布时间】:2016-04-25 01:14:34
【问题描述】:

因为一个例子值一千字,假设我有以下 JSON 流:

{"a": 0, "b": 1}
{"a": 2, "b": 2}
{"a": 7, "b": null}
{"a": 3, "b": 7}

我怎样才能保留.b 属性是[1, 7] 之一的所有对象(实际上列表要长得多,所以我不想这样做select(.b == 1 or .b == 7))。我正在寻找类似这样的内容:select(.b in [1, 7]),但我在手册页中找不到我要寻找的内容。

【问题讨论】:

    标签: jq whitelist


    【解决方案1】:

    使用select($value == $collection[]) 模式可以实现$value in $collection。更有效的选择是select(any($value == $collection[]; .)) 所以你的过滤器应该是这样的:

    [1, 7] as $whitelist | select(any(.b == $whitelist[]; .))
    

    将数组放入变量有其好处,因为它可以让您使用参数轻松更改白名单。

    $ jq --argjson whitelist '[2, 7]' 'select(any(.b == $whitelist[]; .))'
    

    【讨论】:

    • 原来的问题是指流,而不是数组,在这种情况下你不需要使用map。
    • 另外,注意[1, 7][]可以表示为(1, 7)。
    • 最初,问题表明输入是一个数组,但在我回答后改变了。
    • 是的,一旦我看到您的答案,我就编辑问题不好,我只是想让问题更加集中。 @SantiagoLapresta (1, 7) 构造的文档在哪里,我似乎无法在手册页中找到它。
    • @foo:关键在于,使用逗号,表达式会产生多个值。当您在数组上使用 [] 时,该表达式也会产生多个值。我想手册中的相关部分在[,] 上。 [1, 2, 3][] 等价于 1, 2, 3。
    【解决方案2】:

    以下使用 index/1 的方法类似于最初寻求的方法(“.b in [1, 7]”),如果白名单很大,可能比在 select 中使用 .[] 快得多。

    如果你的 jq 支持 --argjson:

    jq --argjson w '[1,7]' '. as $in | select($w | index($in.b))'
    

    否则:

    jq --arg w '[1,7]' '. as $in | ($w|fromjson) as $w | select($w | index($in.b))'
    

    或:

    jq '. as $in | select([1, 7] | index($in.b))'
    

    更新

    2017 年 1 月 30 日,添加了一个名为 IN 的内置函数,用于有效测试 JSON 实体是否包含在流中。它还可以用于有效地测试数组中的成员资格。例如,上面使用 --argjson 的调用可以简化为:

    jq --argjson w '[1,7]' 'select( .b | IN($w[]) )'
    

    如果你的jq没有IN/1,那么只要你的jq有first/1,你就可以使用这个等价的定义:

    def IN(s): . as $in | first(if (s == $in) then true else empty end) // false;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-06
      • 1970-01-01
      • 2012-10-08
      相关资源
      最近更新 更多