【问题标题】:Custom sorting array by groups with Ruby使用 Ruby 按组自定义排序数组
【发布时间】:2017-07-20 06:49:26
【问题描述】:

请您帮忙。我有 3 组值的 input_array。

我需要的组序是:

1st group: Pou
2nd group: Apl
3rd group: Gab

这个顺序已经在 input_array 中完成了,但是我想对每个组进行升序排序。

到目前为止,我的脚本会产生下表中心列中给出的输出(当前输出)。

input_arr = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"] 

b=input_arr.sort_by do |s|
  if s =~ /^\d+$/
      [2, $&.to_i]
  else
      [1, s]
  end
end

puts b

下面也显示了所需的排序输出数组。


 input array  | current output | desired output array

    Pou-12    |     Apl        |      Pou-1
    Pou-7     |     Gab-1      |      Pou-2
    Pou-4     |     Gab-2      |      Pou-3
    Pou-8     |     Gab-3      |      Pou-4
    Pou-9     |     Gab-4      |      Pou-5
    Pou-11    |     Gab-5      |      Pou-6
    Pou-10    |     Pou-1      |      Pou-7
    Pou-3     |     Pou-10     |      Pou-8
    Pou-2     |     Pou-11     |      Pou-9
    Pou-1     |     Pou-12     |      Pou-10
    Pou-6     |     Pou-2      |      Pou-11
    Pou-5     |     Pou-3      |      Pou-12
    Apl       |     Pou-4      |      Apl
    Gab-3     |     Pou-5      |      Gab-1
    Gab-5     |     Pou-6      |      Gab-2
    Gab-4     |     Pou-7      |      Gab-3
    Gab-1     |     Pou-8      |      Gab-4
    Gab-2     |     Pou-9      |      Gab-5

更新

Cary 用数组代替哈希的解决方案。

a = ["Pou-7","Pou-4","Gab-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-1","Pou-12","Gab-2"]
order = [ "Pou", "Apl", "Gab" ]

a.map{ |s| head,tail = s.split("-"); [order.index(head), tail.to_i, s]}.sort.map(&:last)

=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9", 
"Pou-10", "Pou-11", "Pou-12", "Apl", "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]

【问题讨论】:

  • Ger,SO 的惯例是将问题和答案分开,并且在问题的情况下,一旦发布就不要修改它们,除非需要更正或澄清。这在这里无关紧要,但提问者有时会发布他们自己的答案,当他们这样做时,这是作为答案,而不是对问题的修改。
  • 感谢分享,但这样做是惯例还是规则?
  • Ger,我不知道是否有关于此的规则,但如果您查看已被支持的 SO 问题,您将很少会看到提供答案的附录。部分原因可能只是通过将问题和答案分开来减少重复。邀请其他读者提供他们对这个问题的看法。

标签: arrays ruby sorting


【解决方案1】:
a = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2",
     "Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]

order = { "Pou"=>0, "Apl"=>1, "Gab"=>2 }
a.map do |s|
  head, tail = s.split('-')
  [order[head], tail.to_i, s]
end.sort.map(&:last)
  #=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9",
  #    "Pou-10", "Pou-11", "Pou-12", "Apl, "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]

注意head, tail = "Apl".split('-') #=> ["Apl"],所以head #=> "Apl"tail #=> nil,然后是tail.to_i #=> nil.to_i #=> 0

请参阅Array#<=>,了解排序时如何比较数组。

【讨论】:

  • 优秀的卡里。即使输入数组不是按组排序的,它也可以正常工作,打印正确的顺序。非常感谢
  • 感谢 Cary 提供数组的链接。我已经更新了我的原始问题,显示您使用“订单”数组而不是哈希的解决方案。我学到了很多测试更深层次的解决方案。
【解决方案2】:
input = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]      

grouped_by_prefix = input.group_by do |item| 
  item.split('-')[0] 
end

grouped_by_prefix.each do |_, values| 
  values.sort_by! { |value| value.split('-')[1].to_i } 
end

['Pou', 'Apl', 'Gab'].reduce([]) do |memo, key| 
  memo + (grouped_by_prefix[key] || []) 
end

算法不是超级高效(例如双重split操作)但很容易理解

【讨论】:

  • 嗨 djaszczurowski,非常感谢。我也尝试过您的解决方案,它也可以正常工作。优秀的。我将用实际数据进行测试。问候
【解决方案3】:

你可以试试这个:

b = input_arr.group_by { |e| e.split("-")[0] }
b = b.flat_map { |k, v| v.sort_by!{ |vs| vs.split("-")[1].to_i }; v }

【讨论】:

  • 嗨,伙计,非常感谢。非常好。它似乎适用于这个样本。我会用实际数据进行测试。
  • 使用b.flat_map 而不是b.map { ... }.flatten
  • 你好何文。谢谢你的帮助。它工作得很好。我看到的唯一问题是当输入数组的顺序不同时,输出未按规则“Pou、Apl、Gab”排序。例如使用以下输入数组 a = ["Pou-7","Pou-4","Gab-4","Pou-8","Pou-9","Pou-11","Pou-10 ","‌​Pou-3","Pou-2","Pou-‌​1","Pou-6","Pou-5","‌​Apl","Gab-3","Gab -5"‌​,"Gab-1","Pou-12","G‌​ab-2"]
【解决方案4】:

您的初始数组如下所示:

a = ["Pou-12","Pou-7","Pou-4","Pou-8","Pou-9","Pou-11","Pou-10","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab-4","Gab-1","Gab-2"]

d = []

按数组的第一部分对数组进行分组:

c = a.group_by{|b| b.split("-").first}
#=> {"Pou"=>["Pou-12", "Pou-7", "Pou-4", "Pou-8", "Pou-9", "Pou-11",
#=>          "Pou-10", "Pou-3", "Pou-2", "Pou-1", "Pou-6", "Pou-5"],
#=>  "Apl"=>["Apl"],
#=>  "Gab"=>["Gab-3", "Gab-5", "Gab-4", "Gab-1", "Gab-2"]
#=> }

现在,单独对分组数组进行排序:

c.each do |k, v|
  d << v.sort{|b, c| ( b.split("-").last.to_i <=> c.split("-").last.to_i )}
end

最后,由于输出是 Array of Array,所以将其展平:

d.flatten!

#=> ["Pou-1", "Pou-2", "Pou-3", "Pou-4", "Pou-5", "Pou-6", "Pou-7", "Pou-8", "Pou-9", "Pou-10", "Pou-11", "Pou-12", "Apl", "Gab-1", "Gab-2", "Gab-3", "Gab-4", "Gab-5"]

【讨论】:

  • 你滥用Enumerable#each,使用d = c.flat_map { ... }
  • 你好阿比。谢谢你的帮助。它工作得很好。我看到的唯一问题是当输入数组的顺序不同时,输出未按规则“Pou、Apl、Gab”排序。例如使用以下输入数组 a = ["Pou-7","Pou-4","Gab-4","Pou-8","Pou-9","Pou-11","Pou-10 ","Pou-3","Pou-2","Pou-1","Pou-6","Pou-5","Apl","Gab-3","Gab-5","Gab -1","Pou-12","Gab-2"]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 2012-06-24
相关资源
最近更新 更多