Как изменить все ключи хэша на новый набор заданных клавиш?Как изменить все ключи хэша на новый набор заданных клавиш
Есть ли способ сделать это элегантно?
Как изменить все ключи хэша на новый набор заданных клавиш?Как изменить все ключи хэша на новый набор заданных клавиш
Есть ли способ сделать это элегантно?
я предполагаю, что вы хотите изменить хэш 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 "}
Точное решение будет зависеть от формата, что у вас есть новые ключи (или, если вы можете получить новый ключ из старого ключа.)
Если у вас есть хэш 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
Это приведет к удалению значения для' key', когда ' new_keys' случайно случайно возвращает 'key' для некоторого' ключа'. Ответ Барболоса на этот вопрос: http://stackoverflow.com/questions/4137824 преодолевает эту проблему. – sawa
вместо этого вы можете использовать 'h.keys.each {| key | h [new_keys [key]] = h.delete (key)} ' – Selvamani
@Selvamani, см. мой ответ и создайте ответ из вашего комментария. –
Предполагая, что у вас есть Hash
, которая отображает старые ключи от новых ключей, вы могли бы сделать что-то вроде
hsh.map {|k, v| [key_map[k], v] }.to_h
Ты мужчина! Ваш хэш абсолютно потрясающий! Еще раз спасибо за этот камень!:) – CalebHC
Он также предполагает, что у вас есть 'key_map', определяемый как хэш пар ключ/значение, где ключ - это старый ключ, а значение - это новый ключ, который заменяется. –
Если вы беспокоиться о производительности, это быстрее:
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?"
Это прерывается, если' key_map [k] 'nil , –
Другой способ сделать это:
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% окупаются со временем, поэтому учтите это. Пара ответов не была включена, потому что есть потенциальные недостатки, когда они возвращают плохие результаты.
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}
Я думаю, что вызов merge для каждой клавиши будет сравнительно медленным. – Josh
@Josh, вы правы. Я снова запустил тест @ theTinMan с добавлением двух моих методов и получил следующие результаты: «selvamani быстрее, чем ttm на 19.99% ± 1.0%; ttm похож на caryewo (использует' each_with_object'); caryewo похож на mittag; mittag быстрее, чем caryred (использует 'reduce') на 70.0% ± 10.0%". –
Момент самостоятельной рекламы ☺️, но просто чтобы оставить его здесь: если что-то еще более сложное (например, выбирать определенные ключи одновременно или использовать типы ценностей и т. Д.), Я собрал крошечный lib: https : //github.com/smileart/hash_remapper – smileart