24

私はオブジェクトの配列を持っています

[<#a star=1  val=1>, <#a star=nil val=3> , <#a star=2  val=2>]

配列を時間で並べ替え、次に val で並べ替える必要があります

[ <#a star=2  val=2>, <#a star=1  val=1>, <#a star=nil val=3> ]

ただし、時間が nil であるため、sort_by を使用するとエラーがスローされます。

私は今、並べ替えに醜い方法を使用していますが、良い方法があると確信しています

starred=[]
@answers.each {|a| (starred << a) if a.starred }
@answers=@answers-starred
starred=starred.sort_by {|a| a.starred }.reverse
@answers=starred+@answers
4

3 に答える 3

42
starred.sort_by { |a| [a ? 1 : 0, a] }

2 つの要素を比較する必要がある場合は、配列を比較します。Ruby が配列を比較する (メソッドを呼び出す===) 場合、1 番目の要素を比較し、1 番目の要素が等しい場合にのみ 2 番目の要素に進みます。? 1 : 0Fixnum を 1 番目の要素として使用することを保証するため、エラーにはなりません。

を行う? 0 : 1と、nil配列の先頭ではなく末尾に表示されます。
次に例を示します。

irb> [2, 5, 1, nil, 7, 3, nil, nil, 4, 6].sort_by { |i| [i ? 1 : 0, i] }
=> [nil, nil, nil, 1, 2, 3, 4, 5, 6, 7]

irb> [2, 5, 1, nil, 7, 3, nil, nil, 4, 6].sort_by { |i| [i ? 0 : 1, i] }
=> [1, 2, 3, 4, 5, 6, 7, nil, nil, nil]
于 2010-12-18T01:10:52.387 に答える
8

nil を最初に表示する場合 (ゼロ相当):

@answers.sort_by { |a| a.star or 0 }

それらを最後に表示したい場合は、ゼロを Max Int に置き換えることができますが、それはハッキリしすぎます。これはより良いかもしれません:

@answers.select(&:starred?).sort_by(&:star) + @answers.reject(&:starred?)

Nakilon が提供する答えは素晴らしいですが、基本的に 2 つの異なる属性で 2 回並べ替えています。ほとんどの状況では、おそらく十分です。

于 2013-03-27T18:55:15.790 に答える