Come cambio tutte le chiavi di un hash con un nuovo set di chiavi date?Come cambiare tutte le chiavi di un hash con un nuovo set di chiavi date
C'è un modo per farlo con eleganza?
Come cambio tutte le chiavi di un hash con un nuovo set di chiavi date?Come cambiare tutte le chiavi di un hash con un nuovo set di chiavi date
C'è un modo per farlo con eleganza?
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 "}
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
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
invece di questo puoi usare 'h.keys.each {| key | h [new_keys [chiave]] = h.delete (chiave)} ' – Selvamani
@Selvamani, vedi la mia risposta e crea una risposta dal tuo commento. –
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
Sei l'uomo! Il tuo hash è assolutamente fantastico! Grazie ancora per questa gemma!:) – CalebHC
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. –
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?"
Si interrompe se' key_map [k] 'è nullo . –
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.
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}
Penso che chiamare l'unione per ogni chiave sarà relativamente lenta – Josh
@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%". –
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