【问题标题】:Sorting an array of objects in Ruby by object attribute?按对象属性对Ruby中的对象数组进行排序?
【发布时间】:2010-10-27 07:02:45
【问题描述】:

我在 Ruby on Rails 中有一个对象数组。我想按对象的属性对数组进行排序。有可能吗?

【问题讨论】:

    标签: ruby sorting object


    【解决方案1】:

    我建议改用 sort_by:

    objects.sort_by {|obj| obj.attribute}
    

    特别是如果可以计算属性。

    或者更简洁的方法:

    objects.sort_by(&:attribute)
    

    【讨论】:

    • 或简写版本:objects.sort_by(&:attribute)
    • 更短的objects.sort_by &:attribute
    • 如果遇到大小写字母分开排序的问题,可以使用objects.sort_by { |obj| obj.attribute.downcase }
    • 知道这与sort! 相比如何(例如速度等)吗?
    【解决方案2】:

    是的,使用Array#sort! 这很容易。

    myarray.sort! { |a, b|  a.attribute <=> b.attribute }
    

    【讨论】:

    • Thnx 伙计,但它对我没有用,我有一个对象数组。其中对象的属性之一是created_at。我想用这个字段对其进行排序。所以我做了@comm_bytes.sort! {|a, b| a.created_at b.created_at } 但我运气不好,你能帮忙....??
    • 是否有 created_at 方法可以访问@created_at 属性? @created_at 是什么类型的对象?它是否定义了&lt;=&gt;?你得到什么样的错误?等等,等等,令人作呕。换句话说,我们需要比“但我没有运气”更多的细节。
    • 如果你做 myarray = myarray.sort {...} 没有“!”它会工作
    • @Doru 是的,这也有效,但你为什么要这样做?它不那么直接,效率也更低。如果您想保留原件并将结果分配给不同的对象,请使用sort;否则,使用就地变体sort!。事实上,sort 在内部调用了sort!,在复制了原始对象之后。
    • @Doru 代码中的其他地方一定有错误,我可以 100% 向您保证 sort! 会正常工作,并且总是(!)做与您所做的一样的事情写的。
    【解决方案3】:

    升序:

    objects_array.sort! { |a, b|  a.attribute <=> b.attribute }
    

    objects_array.sort_by{ |obj| obj.attribute }
    

    降序:

    objects_array.sort! { |a, b|  b.attribute <=> a.attribute }
    

    objects_array.sort_by{ |obj| obj.attribute }.reverse
    

    【讨论】:

      【解决方案4】:

      如果您需要按两个属性排序,其中第一个比第二个更重要(意味着仅当第一个参数相等时才考虑第二个参数),那么您可以这样做

      myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
      

      或者在数组数组的情况下

      myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
      

      【讨论】:

        【解决方案5】:

        您可以通过重写 方法使任何类可排序:

        class Person
        
          attr_accessor :first_name, :last_name
        
          def initialize(first_name, last_name)
            @first_name = first_name
            @last_name = last_name
          end
        
          def <=>(other)
            @last_name + @first_name <=> other.last_name + other.first_name
          end
        
        end
        

        现在一个 Person 对象数组可以按 last_name 排序。

        ar = [Person.new("Eric", "Cunningham"), Person.new("Homer", "Allen")]
        
        puts ar  # => [ "Eric Cunningham", "Homer Allen"]  (Person objects!)
        
        ar.sort!
        
        puts ar  # => [ "Homer Allen", "Eric Cunningham" ]
        

        【讨论】:

          【解决方案6】:

          更优雅的objects.sort_by(&amp;:attribute),如果需要切换顺序可以加.reverse

          【讨论】:

            【解决方案7】:

            Array#sort 效果很好,如上所述:

            myarray.sort! { |a, b|  a.attribute <=> b.attribute }
            

            但是,您需要确保为该属性实现了 &lt;=&gt; 运算符。如果它是 Ruby 原生数据类型,这不是问题。否则,编写您自己的实现,如果 a b 返回 1。

            【讨论】:

              【解决方案8】:
              【解决方案9】:
              @model_name.sort! { |a,b| a.attribute <=> b.attribute }
              

              【讨论】:

              • 2009年有很多相同的答案,不用再补充了。
              • 在对无法直接比较的对象进行排序时不要使用sort。如果您必须访问属性或进行计算以获取要比较的值,请使用sort_by。它会快得多。
              猜你喜欢
              • 2011-09-06
              • 1970-01-01
              • 2016-11-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-20
              • 2010-11-02
              相关资源
              最近更新 更多