Rubyのオブジェクトの配列をオブジェクト属性で並べ替えますか?


128

Ruby on Railsにオブジェクトの配列があります。オブジェクトの属性で配列を並べ替えたいのですが。出来ますか?

回答:


222

代わりにsort_byを使用することをお勧めします。

objects.sort_by {|obj| obj.attribute}

特に属性が計算される場合があります。

または、より簡潔なアプローチ:

objects.sort_by(&:attribute)

81
または簡略版:objects.sort_by(&:attribute)
Nikola

3
さらに短いobjects.sort_by&:attribute
jasin_89 2013

1
大文字と小文字を別々にソートすることに問題がある場合は、次を使用できますobjects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
これがどのように比較されるのかsort!(たとえば速度など)?
Joshua Pinter 2015


35

はい、Array#sort!これは簡単に使用できます。

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

Thnxバディですが、オブジェクトの配列があるのでうまくいきませんでした。オブジェクトの属性の1つがcreated_atにあります。このフィールドで並べ替えたい。@ comm_bytes.sortをやった!{| a、b | a.created_at <=> b.created_at}ですが、私には運がありません....?

4
@created_at属性にアクセスするcreated_atメソッドはありますか?@created_atはどのようなオブジェクトですか?定義しています<=>か?どのようなエラーが発生していますか?など、悪心。言い換えれば、「私には運がない」よりも詳細な情報が必要です。
ホタルブクロ

「!」なしでmyarray = myarray.sort {...}を実行すると機能します
DoruChidean

@ドルはい、それも機能しますが、なぜそれをするのですか?直接性が低く、効率が悪い。sortオリジナルを保持して結果を別のオブジェクトに割り当てる場合に使用します。それ以外の場合は、インプレースバリアントを使用しsort!ます。実際、元のオブジェクトをコピーした後、内部的にsort呼び出しsort!ます。
Konrad Rudolph

1
@Doruコードのどこかにエラーがあるはずです。問題なく動作することを100%保証できますsort!。常に(!)あなたが書いたものと同じことを行います。
Konrad Rudolph

27

昇順 :

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

20

2つの属性による並べ替えが必要な場合、最初の属性が次に重要で、2番目の属性が重要です(最初の引数が等しい場合にのみ2番目の引数を考慮に入れることを意味します)。次のようにします。

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] }

14

<=>メソッドをオーバーライドすることで、任意のクラスをソート可能にすることができます。

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" ]

10

上記のように、Array#sortは適切に機能します。

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

ただし、<=>その属性に対して演算子が実装されていることを確認する必要があります。Rubyネイティブデータ型の場合、これは問題ではありません。それ以外の場合は、a <bの場合は-1、等しい場合は0、a> bの場合は1を返す独自の実装を記述します。


10

よりエレガントobjects.sort_by(&:attribute).reverse、順序を切り替える必要がある場合は追加できます。



-2
@model_name.sort! { |a,b| a.attribute <=> b.attribute }

2
2009年に投稿された同じ答えはたくさんあります。別の答えを追加する必要はありません。
interjay 2013年

2
sort直接比較できないオブジェクトを並べ替える場合は使用しないでください。属性にアクセスする必要がある場合、または比較する値を取得するために計算を行う必要がある場合sort_by。それははるかに速くなります。
ティンマン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.