【问题标题】:jq unique_by to choose first element after sortjq unique_by 选择排序后的第一个元素
【发布时间】:2020-06-12 17:35:07
【问题描述】:

我有一系列具有相关信号级别的无线接入点。 我想将其减少为具有最高信号的唯一 SSID。

# cat aps.json 
{
 "AP" : [
  { "SSID"  : "Bart",   "Signal" : -20 },
  { "SSID"  : "Lisa",   "Signal" : -19 },
  { "SSID"  : "Homer",  "Signal" : -91 },
  { "SSID"  : "Homer",  "Signal" : -92 },
  { "SSID"  : "Lisa",   "Signal" : -92 },
  { "SSID"  : "Lisa",   "Signal" : -21 },
  { "SSID"  : "Homer",  "Signal" : -90 },
  { "SSID"  : "Bart",   "Signal" : -21 },
  { "SSID"  : "Bart",   "Signal" : -22 }
  ]
}

我尝试使用 sort_by 按 Signal 进行排序,这似乎不知道负数。我使用 reverse 将最小的负数放在第一位。然后 unique_by 似乎没有选择第一个元素。

# jq '.AP | sort_by(.Signal) | reverse | unique_by(.SSID)' aps.json        
[
  {
    "SSID": "Bart",
    "Signal": -22
  },
  {
    "SSID": "Homer",
    "Signal": -92
  },
  {
    "SSID": "Lisa",
    "Signal": -19
  }
]

似乎选择了流中的最后一个 Bart、Second Homer 和 First Lisa。

这个问题的答案 jq unique_by - Choose remaining element 似乎暗示这已在 jq 的更高版本或至少 1.5 中修复,但我正在运行 1.5

# jq --version
jq-1.5

【问题讨论】:

    标签: json sorting unique jq


    【解决方案1】:

    我认为问题是 unique_by() 在选择元素之前进行了预排序。即它正在处理我刚刚排序的传入数据。

    答案是将预先排序的数据呈现给 unique_by()。

    最后一块拼图是删除反向,因为 sort_by 可以否定字段。

    这似乎可以解决问题。

    # jq '.AP | sort_by(.SSID,-.Signal)| unique_by(.SSID)' aps.json 
    [
      {
        "SSID": "Bart",
        "Signal": -20
      },
      {
        "SSID": "Homer",
        "Signal": -90
      },
      {
        "SSID": "Lisa",
        "Signal": -19
      }
    ]
    

    【讨论】:

      【解决方案2】:

      先按.SSID分组,再使用max_by,可以找到解决办法:

      [.AP
       | group_by(.SSID)
       | .[]
       | max_by(.Signal)]
      

      无排序解决方案

      不幸的是,内置的group_by 涉及排序,但通过将group_by 替换为无排序版本,上述方法很容易产生无排序解决方案:

      # NOTE: it is assumed that (stream|f) is a stream of strings
      def GROUPS_BY(stream; f):
        reduce stream as $x ({}; .[$x|f] += [$x] ) | .[] ;
      
      [GROUPS_BY(.AP[]; .SSID)
       | max_by(.Signal)]
      

      (这里定义的GROUPS_BY之所以如此命名是因为它是面向流的。)

      关于sort_by的注释

      关于 Q 中的评论:

      sort_by ...似乎不知道负数

      幸运的是,所有版本的 jq 中的排序过滤器都能正确排序数字,例如

      jq -c sort <<< '[-1,-2,2,1]'
      [-2,-1,1,2]
      

      然而,排序功能的实现有一个重要的变化:

      截至2016年1月18日(7835a72),内置排序过滤器稳定;在此之前,稳定性取决于平台。

      这意味着排序过滤器应该在 jq 1.6 中的所有平台上都是稳定的。

      【讨论】:

      • 我的目标是清晰 - 每一步都在自己的路线上。
      • 谢谢。负数的排序确实有效,我只是需要它们以相反的顺序。
      • @Colin - 最好避免排序,但要获得已排序(非降序)数组的最大值,只需取最后一个元素:.[-1]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      相关资源
      最近更新 更多