2010-10-28 7 views

Antwort

1

Ich gehe davon aus Sie keys den Hash zu ändern, ohne die Werte zu ändern:

hash = {"nr"=>"123", "name"=>"Herrmann Hofreiter", "pferd"=>"010 000 777", "land"=>"hight land"} 
header = ["nr", "name", "hourse", "land"] 
new_hash = header.zip(hash.values).to_h 

Ergebnis: { "nr" => "123", " Name "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," Land "=>" hohes Land "}

+0

Ein Moment der Eigenwerbung but, aber nur um es hier zu belassen: wenn etwas etwas Komplexeres gebraucht wird (zB bestimmte Schlüssel gleichzeitig auswählen oder Werte typisieren usw.), stelle ich eine kleine lib: https zusammen : //github.com/smileart/hash_remapper – smileart

3

Die exakte Lösung würde von dem Format ab, die Sie die neuen Schlüssel haben in (oder wenn Sie den neuen Schlüssel aus dem alten Schlüssel ableiten können.)

Sie haben Unter der Annahme einer Hash-h, deren Schlüssel Sie ändern möchten und ein Hash-new_keys, die die aktuellen Schlüssel zu den neuen Schlüssel Karten könnten Sie tun:

h.keys.each do |key| 
    h[new_keys[key]] = h[key] # add entry for new key 
    k.delete(key)    # remove old key 
end 
+1

Dies wird einen Wert für' key' when 'entfernen new_keys' gibt zufällig 'key' selbst für einen' key' zurück. Die Antwort von barbolos auf diese Frage: http://stackoverflow.com/questions/4137824 überwindet dieses Problem. – sawa

+2

statt dessen können Sie 'h.keys.each {| key | verwenden h [new_keys [key]] = h.delete (key)} ' – Selvamani

+0

@Selvamani, sehe meine Antwort und erstelle eine Antwort aus deinem Kommentar. –

73

Vorausgesetzt Sie haben eine Hash haben die alten Schlüssel zu neuen Schlüssel abbildet, können Sie etwas tun, wie

hsh.map {|k, v| [key_map[k], v] }.to_h 
+4

Sie sind der Mann! Dein Hash ist total genial! Nochmals vielen Dank für dieses Juwel!:) – CalebHC

+1

Es nimmt auch an, Sie haben 'key_map' definiert als ein Hash von Schlüssel/Wert-Paaren, wobei der Schlüssel der alte Schlüssel ist und der Wert der neue Schlüssel ist. –

-1

Wenn Sie auch über die Leistung Sorge, dies ist schneller:

hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] } 

Sie keine neue Hash erstellen und benennen Sie nur die notwendigen Schlüssel. Das gibt Ihnen bessere Leistung.

Sie können mehr Details in "How to elegantly rename all keys in a hash in Ruby?"

+0

Dies bricht, wenn' key_map [k] 'ist null . –

3

Einen anderen Weg, es zu tun finden:

hash = { 
    'foo' => 1, 
    'bar' => 2 
} 

new_keys = { 
    'foo' => 'foozle', 
    'bar' => 'barzle' 
} 

new_keys.values.zip(hash.values_at(*new_keys.keys)).to_h 
# => {"foozle"=>1, "barzle"=>2} 

es nach unten brechen:

new_keys 
.values # => ["foozle", "barzle"] 
.zip(
    hash.values_at(*new_keys.keys) # => [1, 2] 
) # => [["foozle", 1], ["barzle", 2]] 
.to_h 
# => {"foozle"=>1, "barzle"=>2} 

Es ist Benchmark Zeit ..

Während ich die Einfachheit von Jörn Antwort mag, ich bin nicht sicher war, es so schnell war, wie es sein sollte, dann sah ich selvamani Kommentar:

require 'fruity' 

HASH = { 
    'foo' => 1, 
    'bar' => 2 
} 

NEW_KEYS = { 
    'foo' => 'foozle', 
    'bar' => 'barzle' 
} 

compare do 
    mittag { HASH.dup.map {|k, v| [NEW_KEYS[k], v] }.to_h } 
    ttm  { h = HASH.dup; NEW_KEYS.values.zip(h.values_at(*NEW_KEYS.keys)).to_h } 
    selvamani { h = HASH.dup; h.keys.each { |key| h[NEW_KEYS[key]] = h.delete(key)}; h } 
end 

# >> Running each test 2048 times. Test will take about 1 second. 
# >> selvamani is faster than ttm by 39.99999999999999% ± 10.0% 
# >> ttm is faster than mittag by 10.000000000000009% ± 10.0% 

Diese sind sehr nahe beieinander Geschwindigkeit weise ausgeführt, so dass jeder wird tun, aber 39% zahlt sich im Laufe der Zeit aus, also bedenken Sie das. Ein paar Antworten wurden nicht berücksichtigt, da es potenzielle Fehler gibt, die schlechte Ergebnisse liefern.

0
h = { 'foo'=>1, 'bar'=>2 } 
key_map = { 'foo'=>'foozle', 'bar'=>'barzle' } 

h.each_with_object({}) { |(k,v),g| g[key_map[k]]=v } 
    #=> {"foozle"=>1, "barzle"=>2} 

oder

h.reduce({}) { |g,(k,v)| g.merge(key_map[k]=>v) } 
    #=> {"foozle"=>1, "barzle"=>2} 
+0

Ich denke, Aufruf Merge für jede Taste wird vergleichsweise langsam sein – Josh

+0

@Josh, Sie sind richtig. Ich lief mit zwei Methoden erneut in den Benchmark des TInMan und erhielt die folgenden Ergebnisse: "selvamani ist schneller als ttm nach 19,99% ± 1,0%; ttm ist ähnlich wie caryewo (verwendet' each_object'); caryewo ist ähnlich wie Mittag; Mittag ist schneller als caryred (verwendet 'reduce') um 70.0% ± 10.0%". –

Verwandte Themen