【问题标题】:how to check if all elements are equal with jq如何检查所有元素是否与jq相等
【发布时间】:2021-04-02 15:11:31
【问题描述】:

我有来自 curl 的 json 数据,如下所示:

[
   {
     "state": "foo",
   },
   {
     "state": "foo",
   },
   {
     "state": "foo",
   }
]

curl uri | jq .[].state 的输出将是

"foo"
"foo"
"foo"

如何使用 jq 检查所有“状态”值是否相等并在我的条件下使用此 truefalse 状态?在这个例子中,我会得到 true 值。

这里

"foo"
"foo"
"bar"

应该是

【问题讨论】:

    标签: json jq


    【解决方案1】:

    警告:效率极低

    1. 获取所有.state,其中值不是 foo
    2. 检查是否length == 0
    jq 'map(select(.state != "foo")) | length == 0'
    

    Jq▷Play |~| TRUE

    Jq▷Play |~| FALSE

    【讨论】:

      【解决方案2】:

      很容易想出一个低效的解决方案,例如使用mapunique,但也很容易使用all/2 来设计一个高效的通用解决方案。

      考虑以下面向流的函数:

      # Return `true` if s is the empty stream
      def allEquals(s):
        (first(s) // null) as $x | all(s; .==$x);
      

      使用它,我们可以像示例数据一样有效地测试对象数组中所有 .state 值的相等性,同时忽略其他键:

      allEquals(.[].state)
      

      脚注

      当然,如果数组中的对象只有一个键,如 Q 中所示的示例,可以简单地写成:

      .[0] as $x | all(.[]; . == $x)
      

      感谢 jq 对边缘情况的巧妙处理,即使输入数组为空,它也能正常工作。

      【讨论】:

      • 如果对象包含除“状态”之外的其他键,这是否可以扩展以工作?
      • 似乎你的例子让我明白了这一点:[.[].state == ("foo") ] | all
      • @TravErse - 您刚刚找到了另一种使用 map 的方法。也就是说,它是低效的。
      • @peak,请您解释一下 - 您所说的效率低下是什么意思?
      • @TravErse - 计算资源的不必要消耗(时间和/或空间)。就您的解决方案而言,两者都是。事实上,如果您分析解决方案的计算要求,您会发现它通常比 0stone0 的更差。见en.wikipedia.org/wiki/Algorithmic_efficiency
      【解决方案3】:

      此代码 [.[].state == ("foo") ] | all 按预期工作

      【讨论】:

      • 这需要构造一个长度为 N 的新数组(其中 N 是原始数组的长度),然后可能(在最坏的情况下)遍历整个新数组。 ..
      猜你喜欢
      • 2015-02-12
      • 1970-01-01
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 2013-09-19
      相关资源
      最近更新 更多