2009-04-16 5 views
5

ich einen Rubin-Hash zu konvertieren, diewas ist der beste Weg, um einen rubin Hash in ein Array

{ "stuff_attributes" => { 
    "1" => {"foo" => "bar", "baz" => "quux"}, 
    "2" => {"foo" => "bar", "baz" => "quux"} 
    } 
} 

wie diese aussieht und ich möchte es in einen Hash verwandeln, die

{ "stuff_attributes" => [ 
    { "foo" => "bar", "baz" => "quux"}, 
    { "foo" => "bar", "baz" => "quux"} 
    ] 
} 
sieht wie folgt aus

Ich muss auch die numerische Reihenfolge der Schlüssel beibehalten, und es gibt eine variable Anzahl von Schlüsseln. Das obige ist sehr vereinfacht, aber ich habe ein echtes Beispiel an der Unterseite eingefügt. Was ist der beste Weg, dies zu tun?

PS

Es muss auch

Was die Rekursion geht, hier ist rekursiv sein, was wir annehmen können:

1) der Schlüssel, der manipuliert werden muss, wird übereinstimmen/_attributes $/ 2) der Hash wird viele andere Schlüssel haben, die nicht übereinstimmen/_attributes $/ 3) die Schlüssel innerhalb des Hash werden immer eine Nummer 4) ein _attributes Hash kann auf jeder Ebene des Hash unter einem anderen Schlüssel sein

Dieser Hash ist eigentlich der Params-Hash einer Create-Aktion im Controller. Dies ist ein echtes Beispiel dafür, was mit dieser Routine geparst werden muss.

{ 
    "commit"=>"Save", 
    "tdsheet"=>{ 
    "team_id"=>"43", 
    "title"=>"", 
    "performing_org_id"=>"10", 
    "tdsinitneed_attributes"=>{ 
     "0"=>{ 
      "title"=>"", 
      "need_date"=>"", 
      "description"=>"", 
      "expected_providing_organization_id"=>"41" 
      }, 
     "1"=>{ 
      "title"=>"", 
      "need_date"=>"", 
      "description"=>"", 
      "expected_providing_organization_id"=>"41" 
      } 
     }, 
     "level_two_studycollection_id"=>"27", 
     "plan_attributes"=>{ 
      "0"=>{ 
       "start_date"=>"", "end_date"=>"" 
      } 
     }, 
     "dataitem_attributes"=>{ 
      "0"=>{ 
       "title"=>"", 
       "description"=>"", 
       "plan_attributes"=>{ 
        "0"=>{ 
         "start_date"=>"", 
         "end_date"=>"" 
         } 
        } 
       }, 
      "1"=>{ 
       "title"=>"", 
       "description"=>"", 
       "plan_attributes"=>{ 
        "0"=>{ 
         "start_date"=>"", 
         "end_date"=>"" 
         } 
        } 
       } 
      } 
     }, 
    "action"=>"create", 
    "studycollection_level"=>"", 
    "controller"=>"tdsheets" 
} 

Antwort

8

Beachten Sie, dass diese lang sein könnte, wenn alle Schlüssel zu testen sind Zahlen vor dem Konvertieren ...

def array_from_hash(h) 
    return h unless h.is_a? Hash 

    all_numbers = h.keys.all? { |k| k.to_i.to_s == k } 
    if all_numbers 
    h.keys.sort_by{ |k| k.to_i }.map{ |i| array_from_hash(h[i]) } 
    else 
    h.each do |k, v| 
     h[k] = array_from_hash(v) 
    end 
    end 
end 
+0

NameError: undefined lokale Variable oder Methode 'Schlüssel 'für # \t von/Speicher/cait/Entwicklung/app/Helfer/Anwendung_Helper .rb: 6: in 'array_from_hash ' –

+0

nachdem dieser Fehler durch Ändern von k.to_i.to_s == Schlüssel zu k.to_i.to_s == k behoben wurde, funktioniert es einwandfrei! Vielen Dank! –

+0

Sie haben ein paar interessante Ideen hier einzuteilen :) – rfunduk

4

Wenn wir, dass alle Schlüssel sind in der Tat Strings, die auf ganze Zahlen sauber konvertieren annehmen kann, die folgenden funktionieren sollte:

# "hash" here refers to the main hash in your example, since you didn't name it 
stuff_hash = hash["stuff"] 
hash["stuff"] = stuff_hash.keys.sort_by {|key| key.to_i}.map {|key| stuff_hash[key]} 
+0

Wie kann ich das rekursiv tun? Ich habe vergessen, dies in der Frage zu erwähnen: \ –

+0

Könnten Sie ein Beispiel dafür geben, wie die vollständige Struktur zusammengefügt werden könnte? Wie tief muss die Rekursion gehen, und wie können wir unterscheiden zwischen Hashes, die konvertiert werden müssen und Hashes, die das nicht tun (wie das innere {"foo" => "bar", "baz" => "quux") })? –

+0

hinzugefügt einige Regeln am Ende der Frage, Thx für die Hilfe :) –

0

Um ein bisschen Freiheit zu nehmen, poste ich ein sehr ähnliches Codebeispiel zu Vincent Roberts.

Dieser ist Patches Hash Klasse mit einer Methode.

class Hash 
    def to_array(h = self) 
    return h unless h.is_a? Hash 
    if h.keys.all? { |k| k.to_i.to_s == k } # all keys are numbers so make an array. 
     h.keys.sort_by{ |k| k.to_i }.map{ |i| self.to_array(h[i]) } 
    else 
     h.each do |k, v| 
     h[k] = self.to_array(v) 
     end 
    end 
    end 
end 

Es macht die Verwendung etwas bequemer.

Verwandte Themen