自定义对另一个字符串数组进行排序的字符串-Ruby

时间:2019-04-08 23:27:15

标签: ruby-on-rails arrays ruby string sorting

我有一个当前按字母顺序排序的数组,我正在尝试按手动的字符串顺序对其进行排序。

当前代码:

list = ["gold","silver","bronze","steel","copper"]

list = list.sort { |a, b| a <=> b }

我要实现的目标:(使用空白条目作为分隔符)

list = ["gold","silver","bronze","steel","copper"]

sort_order = ["bronze","silver","gold","","copper","steel"]

list = list.sort_by sort_order

输出:青铜|银|黄金| -|铜|钢

这可能吗?当前停留在以下错误消息中:

comparison of Integer with nil failed
comparison of String with String failed

2 个答案:

答案 0 :(得分:2)

我认为:

  • list的每个元素都在sort_order中;
  • sort_order可能包含不在list中的元素;
  • list可能包含重复项;和
  • sort_order不包含重复项。

如果sort_order最初包含重复项,则可以在计算中使用临时数组sort_order.uniq

观察到,如果list不包含重复项,并且sort_order不包含list中的元素,请按照list的顺序对其进行排序sort_order中的元素很小,因为它只返回sort_order

与使用sortsort_byO(n)O(n*log(n))计算复杂度的方法相比,以下方法更有效。

list = ["gold", "copper", "silver", "copper", "steel", "gold"]
sort_order = ["bronze", "silver", "tin", "gold", "copper", "steel"]

count = list.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
  #=> {"gold"=>2, "copper"=>2, "silver"=>1, "steel"=>1} 
sort_order.flat_map { |e| [e]*count[e] }.reject(&:empty?)
  #=> ["silver", "gold", "gold", "copper", "copper", "steel"] 

答案 1 :(得分:1)

您可能只想制作带有数字等级和字符串名称的奖牌类之类的东西,然后按等级排序即可。像这样

class Medal
  attr_accessor :name, :rank

  def initialize(name, rank)
    @name = name
    @rank = rank
  end
end

list = [Medal.new("gold", 0), Medal.new("silver", 1), Medal.new("bronze", 2), Medal.new("steel", 4), Medal.new("copper", 3)]

list = list.sort_by &:rank

如果需要,可以更进一步,并定义奖牌名称映射到等级,以将等级从初始位置降低。如果需要的话,也可以将每块奖牌定义为一个常量,因为您可能只有一个固定的列表。

但是,如果您不想这样做,那么您可能也可以只列出订单并按索引排序,就像这样

list = ["gold","silver","bronze","steel","copper"]

sort_order = ["bronze","silver","gold","","copper","steel"]

list = list.sort_by {|m| sort_order.index m}