我有一个当前按字母顺序排序的数组,我正在尝试按手动的字符串顺序对其进行排序。
当前代码:
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
答案 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
。
与使用sort
或sort_by
(O(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}