2010-12-18 55 views
16

我有對象的數組排序基於屬性的陣列,其可以在某些元素是nil

[<#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> ] 

但使用sort_by會拋出錯誤,因爲時間爲零。

我使用的是醜陋的方式,現在進行排序,但我相信有一個很好的方式去了解它

starred=[] 
@answers.each {|a| (starred << a) if a.starred } 
@[email protected] 
starred=starred.sort_by {|a| a.starred }.reverse 
@[email protected] 

回答

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

當它來比較兩個元素,它比較的數組。當Ruby比較數組(調用===方法)時,它會比較第一個元素,並且僅在第一個元素相等時纔會轉到第二個元素。我們將Fixnum作爲第一個元素,所以它應該沒有錯誤。

如果你做? 0 : 1nil將出現在數組的末尾而不是開始。
下面是一個例子:

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

如果你想尼爾斯出現第一(零當量):

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

如果你想使他們最後出現,可以更換Max Int爲零,但感覺太冒險了。這可能會更好:

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

由Nakilon提供的答案是輝煌的,但你基本上排序的兩倍,在兩個不同的屬性。在大多數情況下,這可能就足夠了。

+3

感謝@阿明 - 阿里亞納,您的解決方案爲我工作,我認爲是更具可讀性。 – monteirobrena 2014-08-28 13:00:14

+1

這不像OP的初始代碼那樣對於像'-5'這樣的負值 – Nakilon 2016-04-29 13:39:52

0

只需使用value.to_i

starred.sort_by { |a| a.to_i }.reverse 
相關問題