【问题标题】:Custom Sort array of strings by another array of strings - Ruby自定义按另一个字符串数组排序字符串数组 - Ruby
【发布时间】:2019-08-30 04:12:20
【问题描述】:

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

当前代码:

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

【问题讨论】:

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


    【解决方案1】:

    我假设:

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

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

    请注意,如果像示例中一样,list 不包含重复项,并且 sort_order 不包含除 list 中的元素之外的元素,那么按照 sort_order 中元素的顺序对 list 进行排序是微不足道的,因为它只返回sort_order

    以下方法比使用 sortsort_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"] 
    

    【讨论】:

    • sort_order.each_with_index.to_h?
    • 一次性生成count表。
    • 但这会生成#=&gt; {"bronze"=&gt;0, "silver"=&gt;1, "gold"=&gt;2, "copper"=&gt;3, "steel"=&gt;4}。我需要{"gold"=&gt;2, "copper"=&gt;2, "silver"=&gt;1, "steel"=&gt;1}
    • 我认为你比我更了解这个问题,因为这个问题本身对我来说没有意义。
    【解决方案2】:

    您可能只想制作一个奖牌类或其他东西,带有一个数字排名和一个字符串名称,然后按排名排序。像这样。

    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}
    

    【讨论】:

      猜你喜欢
      • 2020-05-29
      • 2014-04-23
      • 2021-06-25
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 2014-03-23
      • 2012-07-20
      • 1970-01-01
      相关资源
      最近更新 更多