2010-10-28 4 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", " name "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," land "=>" high land "}

+0

Момент самостоятельной рекламы ☺️, но просто чтобы оставить его здесь: если что-то еще более сложное (например, выбирать определенные ключи одновременно или использовать типы ценностей и т. Д.), Я собрал крошечный lib: https : //github.com/smileart/hash_remapper – smileart

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' для некоторого' ключа'. Ответ Барболоса на этот вопрос: http://stackoverflow.com/questions/4137824 преодолевает эту проблему. – sawa

+2

вместо этого вы можете использовать 'h.keys.each {| key | h [new_keys [key]] = h.delete (key)} ' – Selvamani

+0

@Selvamani, см. мой ответ и создайте ответ из вашего комментария. –

73

Предполагая, что у вас есть Hash, которая отображает старые ключи от новых ключей, вы могли бы сделать что-то вроде

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

Ты мужчина! Ваш хэш абсолютно потрясающий! Еще раз спасибо за этот камень!:) – CalebHC

+1

Он также предполагает, что у вас есть 'key_map', определяемый как хэш пар ключ/значение, где ключ - это старый ключ, а значение - это новый ключ, который заменяется. –

-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] 'nil , –

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

Я думаю, что вызов merge для каждой клавиши будет сравнительно медленным. – Josh

+0

@Josh, вы правы. Я снова запустил тест @ theTinMan с добавлением двух моих методов и получил следующие результаты: «selvamani быстрее, чем ttm на 19.99% ± 1.0%; ttm похож на caryewo (использует' each_with_object'); caryewo похож на mittag; mittag быстрее, чем caryred (использует 'reduce') на 70.0% ± 10.0%". –

Смежные вопросы