Как изменить все ключи хэша на новый набор заданных ключей
Как изменить все ключи хэша на новый набор заданных клавиш?
Есть ли способ сделать это элегантно?
Ответы
Ответ 1
В Ruby 2.5 есть Hash # transform_keys! метод. Пример использования карты ключей
h = {a: 1, b: 2, c: 3}
key_map = {a: 'A', b: 'B', c: 'C'}
h.transform_keys! {|k| key_map[k]}
# => {"A"=>1, "B"=>2, "C"=>3}
Вы также можете использовать символ # toproc ярлык с transform_keys Например:
h.transform_keys! &:upcase
# => {"A"=>1, "B"=>2, "C"=>3}
Ответ 2
Предполагая, что у вас есть Hash
, который отображает старые ключи на новые ключи, вы можете сделать что-то вроде
hsh.map {|k, v| [key_map[k], v] }.to_h
Ответ 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
Ответ 4
Другой способ сделать это:
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% рассчитывается с течением времени, поэтому подумайте об этом. Пара ответов не была включена, потому что есть потенциальные недостатки, когда они возвращают плохие результаты.
Ответ 5
я предполагаю, что вы хотите изменить хэш- keys
без изменения значений:
hash = {
"nr"=>"123",
"name"=>"Herrmann Hofreiter",
"pferd"=>"010 000 777",
"land"=>"hight land"
}
header = ["aa", "bb", "cc", "dd"]
new_hash = header.zip(hash.values).to_h
Результат:
{
"aa"=>"123",
"bb"=>"Herrmann Hofreiter",
"cc"=>"010 000 777",
"dd"=>"high land"
}
Ответ 6
Если вы также беспокоитесь о производительности, это быстрее:
hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] }
Вы не создаете новый хэш и переименовываете только нужные ключи. Это дает вам лучшую производительность.
Вы можете найти более подробную информацию в разделе Как элегантно переименовать все ключи в хеше в Ruby?"
Ответ 7
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}