2010-10-28 60 views

回答

1

我假定要更改的哈希keys而不改變值:

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 

結果: { 「NR」=> 「123」,「名稱「=>」Herrmann Hofreiter「,」hourse「=>」010 000 777「,」land「=>」高地「}

+0

一段時間的自我提升☺️,但只是把它留在這裏:如果需要更復雜一點(比如同時選擇特定的鍵或脅迫值的類型等),我將一個小小的lib:https ://github.com/smileart/hash_remapper – smileart 2017-12-05 20:49:09

3

確切的解決方案將取決於格式,你必須在新的鍵(或者,如果你能得到從舊的密鑰新的密鑰。)

假設你有一個哈希要修改h,它的鍵和散列new_keys映射當前鍵將新的密鑰,你可以這樣做:

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

這將刪除'key'的值, new_keys'不小心碰巧返回'key'本身的某個'key'。 barbolos的這個問題的答案:http://stackoverflow.com/questions/4137824克服了這個問題。 – sawa 2012-10-24 11:06:26

+2

代替這個,你可以使用'h.keys.each {| key | h [new_keys [key]] = h.delete(key)}' – Selvamani 2015-10-16 05:16:23

+0

@Selvamani,查看我的答案,並從您的評論中創建答案。 – 2016-03-28 22:58:39

73

假設你有一個Hash其舊鍵映射到新鍵,你可以不喜歡

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

你是男人!你的hash是完全可怕的!再次感謝這寶石!:) – CalebHC 2011-09-23 22:55:00

+1

它還假定您有'key_map'定義爲鍵/值對的哈希,其中鍵是舊鍵,值是正在交換的新鍵。 – 2016-03-28 22:35:50

-1

如果你還擔心性能,這是速度快:

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

你不創建一個新的Hash,你只重命名必需的密鑰。這給你更好的表現。

您可以找到 「How to elegantly rename all keys in a hash in Ruby?

+0

如果'key_map [k]'爲零。 – 2016-03-28 22:32:20

3

更多詳情另一種方式來做到這一點是:

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} 

其分解:

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

它的基準時間.. 。

雖然我喜歡喬恩的回答簡單,我不知道這是因爲快,因爲它應該是,然後我看到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% 

這些正在運行的非常接近的速度明智的,所以任何將會這樣做,但是隨着時間的推移,39%的回報將會如此。不包括幾個答案,因爲他們可能會返回不良結果的潛在缺陷。

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} 

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

我認爲爲每個鍵調用合併會比較慢 – Josh 2017-10-24 04:38:49

+0

@Josh,你是對的。我用添加的兩種方法重新運行@TinMan的基準測試,並得到以下結果:「selvamani比ttm快19.99%±1.0%; ttm與caryewo相似(使用'each_with_object'); caryewo與mittag相似; mittag比使用「減少」的速度快70.0%±10.0%「。 – 2017-10-24 05:29:16