2013-03-14 19 views
10

Desidero specificare un metodo di blocco personalizzato per ordinare un array di oggetti in ruby, valutando due proprietà. Tuttavia dopo molte ricerche in google non ho avuto alcun esempio senza l'operatore < =>.metodo di ordinamento personalizzato in rubino

questo è quello che voglio fare: confrontando un vs B:

if a.x less than b.x return -1 
if a.x greater than b.x return 1 
if a.x equals b.x, then compare by another property , like a.y vs b.y 

questo è il mio codice (niubbo in rubino, sorry) e non funziona ...

ar.sort! do |a,b| 
    if a.x < b.y return -1 
    elseif a.x > b.x return 1 
    else return a.y <=> b.y 
end 

Questo blocco è all'interno di una funzione, quindi il ritorno sta uscendo dalla funzione e restituisce -1 ... apprezzerò qualsiasi aiuto su questo.

Cordiali saluti.

+0

perché non usi il metodo di ordinamento? –

+0

@Gashner Lo sto usando, ma ho intenzione di personalizzare la valutazione. – alexserver

+0

Perché è '<=>' escluso? Perché vuoi farlo nel modo più duro? –

risposta

13

Con istruzione case:

ar.sort do |a, b| 
    case 
    when a.x < b.x 
    -1 
    when a.x > b.x 
    1 
    else 
    a.y <=> b.y 
    end 
end 

Con ternario:

ar.sort { |a,b| a.x < b.x ? -1 : (a.x > b.x ? 1 : (a.y <=> b.y)) } 
+0

Grazie, ha funzionato! – alexserver

+5

Una dichiarazione ternaria multilivello in rubino è scoraggiata per motivi di leggibilità/manutenzione. –

23

questo vi darà ordine crescente per x poi per y:

points.sort_by{ |p| [p.x, p.y] } 
+0

+1 per 'sort_by' e' Array # <=> 'che ha esattamente l'OP della semantica desidera. – dbenhur

+0

Questo è molto elegante! Ben fatto - dovrebbe essere la risposta accettata, IMHO – Sebastian

0

Questo sembra funzionare:

# Ascending 
ar.sort! do |a,b| 
    (a-b).abs() > 0 ? a-b : 0 
end 

# Descending 
ar.sort! do |a,b| 
    (a-b).abs() > 0 ? b-a : 0 
end 

Non c'è bisogno dell'operatore della navicella spaziale (<=>) - sembra essere superfluo in Ruby (in termini di efficienza della sintassi), perché Ruby considera lo 0 vero, e per questo uso specifico (sopra), si può semplicemente mettere l'esplicito 0 nell'operatore ternario.

Problemi correlati