2010-10-28 17 views

risposta

1

Presumo che si desidera modificare l'hash keys senza modificare i valori:

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 

risultato: { "nr" => "123", " nome "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," land "=>" high land "}

+0

Un momento di auto-promozione ☺️, ma solo per lasciarlo qui: se qualcosa di un po 'più complesso è necessario (come selezionare chiavi particolari allo stesso tempo o forzare i valori dei tipi e così via), ho messo insieme una piccola lib: https : //github.com/smileart/hash_remapper – smileart

3

La soluzione esatta dipenderebbe dal formato che si hanno le nuove chiavi in ​​(o se è possibile derivare la nuova chiave dalla vecchia chiave.)

Supponendo di avere un hash h le cui chiavi che si desidera modificare e un hash new_keys che mappa le chiavi attuali per le nuove chiavi che si poteva fare:

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

Questo rimuoverà un valore per' key' quando ' new_keys' accidentalmente capita di restituire 'key' stessa per alcuni' key'. la risposta di barbolos a questa domanda: http://stackoverflow.com/questions/4137824 risolve questo problema. – sawa

+2

invece di questo puoi usare 'h.keys.each {| key | h [new_keys [chiave]] = h.delete (chiave)} ' – Selvamani

+0

@Selvamani, vedi la mia risposta e crea una risposta dal tuo commento. –

73

Supponendo di avere un Hash che le mappe vecchie chiavi di nuove chiavi, si potrebbe fare qualcosa di simile

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

Sei l'uomo! Il tuo hash è assolutamente fantastico! Grazie ancora per questa gemma!:) – CalebHC

+1

Si presuppone inoltre che sia stato definito 'key_map' come un hash di coppie chiave/valore in cui la chiave è la vecchia chiave e il valore è la nuova chiave inserita. –

-1

Se ti preoccupi anche di prestazioni, questo è più veloce:

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

Non crea una nuova hash e si rinomina solo le chiavi necessarie. Questo ti dà prestazioni migliori.

è possibile trovare ulteriori dettagli in "How to elegantly rename all keys in a hash in Ruby?"

+0

Si interrompe se' key_map [k] 'è nullo . –

3

Un altro modo per farlo è:

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} 

scomponendola:

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

E 'il momento di riferimento ..

Mentre mi piace la semplicità della risposta di Jörn, io non sono stato sicuro che fosse veloce come dovrebbe essere, poi ho visto il commento di selvamani:

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% 

Questi sono in esecuzione molto vicini velocità insieme saggio, in modo che qualsiasi lo farà, ma il 39% paga nel tempo, quindi consideralo. Un paio di risposte non sono state incluse perché ci sono potenziali difetti in cui potrebbero restituire risultati negativi.

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} 

o

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

Penso che chiamare l'unione per ogni chiave sarà relativamente lenta – Josh

+0

@Josh, sei corretto. Ho ripetuto il benchmark di theTinMan con i miei due metodi aggiunti e ottenuto i seguenti risultati: "selvamani è più veloce di ttm del 19,99% ± 1,0%; ttm è simile a caryewo (usa' each_with_object'); caryewo è simile a mittag; mittag è più veloce di caryred (usa 'reduce') del 70,0% ± 10,0%". –

Problemi correlati