2010-12-18 10 views
16

mam szereg obiektówsortowania tablicy na podstawie atrybutu, który może być zero w niektórych elementów

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

trzeba tablicy się według czasu, a następnie przez val

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

ale użycie sort_by powoduje błąd, ponieważ czas jest zerowy.

Używam brzydki sposób uporządkować teraz, ale jestem pewien, że jest to dobry sposób, aby przejść o to

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

Odpowiedz

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

Kiedy musi porównać dwa elementy, porównuje e tablice . Kiedy Ruby porównuje tablice (wywołuje metodę ===), porównuje pierwszy element i przechodzi do 2. elementów tylko wtedy, gdy 1. są równe. ? 1 : 0 gwarantuje, że będziemy mieć Fixnum jako pierwszy element, więc nie powinien to być żaden błąd.

Jeśli wykonasz ? 0 : 1, nil pojawi się na końcu tablicy zamiast na początku.
Oto przykład:

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

Jeśli chcesz, Nils pojawiać pierwsze (zero-odpowiednik):

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

Jeśli chcesz uczynić je pojawiają się ostatni, można zastąpić zero z Max Int, ale to wydaje się zbyt hackowe. To może być lepiej:

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

Odpowiedź udzielana przez Nakilon jest genialny, choć jesteś w zasadzie sortowania dwukrotnie, na dwóch różnych atrybutów. W większości sytuacji prawdopodobnie wystarczy.

+3

Dzięki @ amin-Ariana, rozwiązanie pracował dla mnie i myślę, że jest bardziej czytelny. – monteirobrena

+1

To nie jest zgodne z początkowym kodem OP dla wartości ujemnych, takich jak "-5" – Nakilon

0

Wystarczy użyć value.to_i

starred.sort_by { |a| a.to_i }.reverse 
Powiązane problemy