2017-03-21 5 views
-1

Ich lerne Ruby und begann gerade mit der Sortierung. Ich versuche, das Array so zu sortieren: [1,3,5,2,4,6] und ich verstehe nicht wirklich, was mit dem Code nicht stimmt. Jede Hilfe wäre willkommen!Ruby Sortierung gerade und ungerade Zahlen Ausgabe

[1,2,3,4,5,6].sort do |x,y| 
    if x.odd? and y.odd? 
    0 
    elsif x.odd? 
    -1 
    else 
    1 
end 
    if (x.odd? && y.odd?) or (x.even? && y.even?) 
    x <=> y 
end 
end 

Antwort

4

Zuerst weg, lassen Sie uns Ihre Einbuchtung reparieren (und konvertieren Standard-Stil Ruby-Community-Codierung), so dass wir besser sehen, was los ist:

[1, 2, 3, 4, 5, 6].sort do |x, y| 
    if x.odd? && y.odd? 
    0 
    elsif x.odd? 
    -1 
    else 
    1 
    end 

    if (x.odd? && y.odd?) || (x.even? && y.even?) 
    x <=> y 
    end 
end 

Nun wird das Problem offensichtlich: Ihre Der erste Bedingungsausdruck ergibt 0, -1 oder 1, aber wird nichts mit diesem Wert getan. Der Wert wird nicht in einer Variablen gespeichert, nicht als Argument übergeben, nicht zurückgegeben. Es wird einfach ignoriert. Der gesamte Ausdruck ist ein NO-OP.

was bedeutet, dass das einzige, was diese zählt, ist:

if (x.odd? && y.odd?) || (x.even? && y.even?) 
    x <=> y 
    end 

Diese Rückkehr wird 0 für zwei Elemente, die gleich sind, -1 oder 1 für zwei Elemente, die ungleich aber beide ungerade oder beide auch sind, und nil (was zu sort bedeutet "diese beiden Elemente sind nicht vergleichbar, sie haben keine definierte relative Reihenfolge") für Elemente, bei denen ein Element ungerade und eins ist gerade. Da sort erfordert, dass alle Elemente vergleichbar sind, wird es dann abgebrochen.

Der einfachste Weg, um dieses Problem zu nähern würde wahrscheinlich das Array in Chancen und Evens zu partitionieren sein, sortieren sie getrennt, und sie dann verketten:

[1, 2, 3, 4, 5, 6].partition(&:odd?).map(&:sort).inject(:concat) 
#=> [1, 3, 5, 2, 4, 6] 

Oder es anders machen rund, sortieren sie einfach alle, und dann Partition (Thanks @Eric Duminil):

[1, 2, 3, 4, 5, 6].sort.partition(&:odd?).inject(:concat) 
#=> [1, 3, 5, 2, 4, 6] 
+2

Schöner One-Liner. Sie könnten sogar 'map' entfernen, indem Sie zuerst sortieren und dann partitionieren:' [3, 2, 1, 5, 6, 4] .sort.partition (&: odd?). Inject (: concat) ' –

+1

Oder' [1 , 2,3,4,5,6] .sort_by {| i | [ich.odd] ? 0: 1, i]} ' – Stefan

+0

@Stefan. [Danke] (http://stackoverflow.com/a/42929315/6419007) –

1

Es ist wahrscheinlich das erste Mal habe ich eine negative modulo:

  • i % -2 ist -1 wenn i ungerade ist
  • i % -20 ist, wenn auch i

ist so von i % -2 ersten und dann durch i Sortier sollte das gewünschte Ergebnis erzielen.

Wenn Sie gerade Zahlen vor ungeraden Zahlen wünschen, können Sie nach i % 2 sortieren.


[3, 2, 1, 5, 6, 4].sort_by{ |i| [ i % -2, i] } 
#=> [1, 3, 5, 2, 4, 6] 

Dank @Stefan für seine ursprüngliche Idee!

+0

Gut zu wissen, dass es eine Anwendung für negative modulo: -D gibt – Stefan

Verwandte Themen