【问题标题】:Find common keys in JSON objects using jq使用 jq 在 JSON 对象中查找公共键
【发布时间】:2019-07-18 21:53:05
【问题描述】:

鉴于我们不知道文件中键的名称,我正在尝试查找 Json 文件中的所有常用键。

Json 文件如下所示:

{
   "DynamicKey1" : {
    "foo" : 1,
    "bar" : 2

   },
   "DynamicKey2" : {
     "bar" : 3

   },
   "DynamicKey3" : {
     "foo" : 5,
     "zyx" : 5

   }   
}

预期结果:

{
 "foo"
}

我试图在这里应用 reduce/foreach 逻辑,但我不确定如何在 jq 中编写它。感谢您的帮助!

jq '. as $ss | reduce range(1; $ss|length) as $i ([]; . + reduce ($ss[i] | keys) as $key ([]; if $ss[$i - 1] | has($key) then . +$key else . end))' file.json

【问题讨论】:

    标签: json key jq set-intersection


    【解决方案1】:

    发布的 Q 中有一些不一致之处:没有所有对象共有的键,如果查看键的成对交集,结果将同时包含“foo”和“bar”。

    在下文中,我将介绍这两个问题的解决方案。

    键入多个对象

    [.[] | keys_unsorted[]] | group_by(.)[] | select(length>1)[0]
    

    所有对象的键

    这是使用类似方法的解决方案:

    length as $length
    | [.[] | keys_unsorted[]] | group_by(.)[]
    | select(length==$length) 
    | .[0]
    

    这涉及到group_by/2,它是使用排序实现的。

    这是一种替代方法,它依赖于内置函数keys 进行排序(重点是 ((nk ln(nk)) - n(k ln(k))) = nk ln( n),即拥有 n 小类 k 项优于一大类 n*k 项):

    # The intersection of an arbitrary number of sorted arrays
    def intersection_of_sorted_arrays:
      # intersecting/1 returns a stream
      def intersecting($A;$B):
        def pop:
        .[0] as $i
        | .[1] as $j
        | if $i == ($A|length) or $j == ($B|length) then empty
          elif $A[$i] == $B[$j] then $A[$i], ([$i+1, $j+1] | pop)
          elif $A[$i] <  $B[$j] then [$i+1, $j] | pop
          else [$i, $j+1] | pop
          end;
        [0,0] | pop;
       reduce .[1:][] as $x (.[0]; [intersecting(.; $x)]);
    

    计算所有对象共有的键:

    [.[] | keys] | intersection_of_sorted_arrays
    

    【讨论】:

    • 谢谢!我找到了一种方法来实现这一点(有点)。但是您的解决方案要好得多!
    【解决方案2】:

    这是一个无需排序且省时的答案,它依赖于 jq 在 JSON 字典中执行查找的效率。由于键是字符串,我们可以简单地使用“词袋”的概念(bow):

    def bow(stream): 
      reduce stream as $word ({}; .[$word|tostring] += 1);
    

    我们现在可以解决“所有对象共有的键”问题如下:

    length as $length
    | bow(.[] | keys_unsorted[])
    | to_entries[]
    | select(.value==$length).key
    

    对于“多个对象中的键”问题也是如此。

    当然,要达到时间效率,还有通常的时空权衡。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      相关资源
      最近更新 更多