2016-10-12 7 views
1

Ich habe eine Reihe von Hashes, die ich basierend auf den :reference Werte sortieren möchte. Einige der Elemente innerhalb des Arrays haben jedoch keinen :reference-Schlüssel und können daher nicht sortiert werden. Gibt es eine Möglichkeit, dieses Feld zu ignorieren und nur die Hash-Elemente zu sortieren, die diesen Schlüssel enthalten?Ruby Sortierung Hashes innerhalb Array

Ich habe den folgenden Ansatz versucht, aber ich bin immer ein Argument Fehler

ArgumentError: comparison of NilClass with String failed 
    sort_by at org/jruby/RubyEnumerable.java:503 



arr1 = [{:reference=> "F123", 
      :name=> "test4" 
      }, 
      { 
      :reference=> "ZA4", 
      :name=> "test3" 
      }, 
      { 
      :reference=> "A43", 
      :name=> "test2" 
      }, 
      { 
      :name=> "test1" 
      }, 
      { 
      :name=> "homework1" 
      }] 

arr1 = arr1.sort_by { |hash| hash[:reference] } 

puts arr1 

Die richtige Ausgabe sollte wie folgt aussehen:

=> arr1= [ 
     {:reference=>"A43", :name=>"test2"}, 
     {:reference=>"F123", :name=>"test4"}, 
     {:reference=>"ZA4", :name=>"test3"}, 
     {:name=> "test1"}, 
     {:name=> "homework1"} 
     ] 

Antwort

3

Sie können nur sortieren auf Werte, die sein kann, verglichen, also wenn Sie Werte verschiedener Typen haben, ist es am besten, sie zuerst in den gleichen Typ zu konvertieren. Eine einfache Work-around ist auf Zeichenfolge zu konvertieren:

arr1.sort_by { |hash| hash[:reference] || '' } 

bearbeiten: Wenn Sie die letzten sortiert nil Werte wollen:

arr1.sort_by { |hash| hash[:reference].to_s } 

Sie auch einen Standard zuweisen können

arr1.sort_by { |hash| [ hash[:reference] ? 0 : 1, hash[:reference].to_s ] } 
+0

Ihnen danken. Gibt es eine Möglichkeit, das Array so zu sortieren, dass die Hashes ohne die Schlüssel ': reference' auf der Rückseite des Arrays enden? – danynl

+0

Ich habe eine Methode hinzugefügt, um diese an das Ende zu schieben, indem ein zweites Element zu ihrer Sortierung hinzugefügt wird, um sie zurück zu zwingen. Ein Array ist eine bequeme Möglichkeit, dies zu tun, da es basierend auf dem ersten Element * dann * dem zweiten Element sortiert ist. – tadman

+0

Sie brauchen '.to_s' nicht in Ihrer letzten Zeile. Strings werden niemals mit "nil" und "nil <=> nil # => 0" verglichen. –

1

Wenn Sie temporäre Variablen nicht stören, können Sie das Array in zwei Arrays aufteilen, eines mit Hashes mit :reference und th e andere Personen ohne:

with_ref, without_ref = arr1.partition { |h| h[:reference] } 

sortieren Dann wird die erste:

with_ref.sort_by! { |h| h[:reference] } 

Und schließlich beide Arrays verketten:

arr1 = with_ref + without_ref