2010-12-18 6 views
16

in einigen Elementen Null sein kann, ich habe ein Array von Objektenein Array auf einem Attribut basiert Sortierung, die

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

i das Array müssen von Zeit sortiert werden, dann durch val

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

aber die Verwendung von sort_by löst einen Fehler aus, weil die Zeit null ist.

ich eine hässliche Art und Weise bin mit jetzt zu sortieren, aber ich bin sicher, dass es eine schöne Möglichkeit, darüber

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

Antwort

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

zu gehen, wenn es zwei Elemente vergleichen hat, ist es eine Arrays vergleicht . Wenn Ruby Arrays vergleicht (Aufrufe der Methode ===), vergleicht es das erste Element und geht nur dann zu den zweiten Elementen, wenn die ersten gleich sind. ? 1 : 0 garantiert, dass wir Fixnum als erstes Element haben, also sollte es kein Fehler sein.

Wenn Sie ? 0 : 1 tun, erscheint nil am Ende des Arrays anstelle von Anfang.
Hier ist ein Beispiel:

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

Wenn Sie die nils wollen zuerst (Null-Äquivalent) erscheinen:

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

Wenn Sie wollen, dass sie erscheinen zuletzt machen, können Sie die ersetzen Null mit einem Max Int, aber das fühlt sich zu hacky an. Dies könnte besser sein:

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

Die Antwort zur Verfügung gestellt von Nakilon brillant, wenn Sie zweimal im Wesentlichen zu sortier, auf zwei verschiedenen Attributen. Für die meisten Situationen ist es wahrscheinlich ausreichend.

+3

Thanks @ amin-ariana, Ihre Lösung für mich gearbeitet und ich denke, besser lesbar ist. – monteirobrena

+1

Dies verhält sich nicht so wie der ursprüngliche Code von OP für negative Werte wie '-5' – Nakilon

0

Verwenden Sie einfach value.to_i

starred.sort_by { |a| a.to_i }.reverse 
Verwandte Themen