Как изменить все ключи хэша новым набором заданных ключей - PullRequest
46 голосов
/ 28 октября 2010

Как мне изменить все ключи хэша с помощью нового набора заданных ключей?

Есть ли способ сделать это элегантно?

Ответы [ 7 ]

77 голосов
/ 28 октября 2010

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

hsh.map {|k, v| [key_map[k], v] }.to_h
9 голосов
/ 26 сентября 2018

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. Например:

h.transform_keys! &:to_s
# => {"a"=>1, "b"=>2, "c"=>3}
3 голосов
/ 02 октября 2017

Я предполагаю, что вы хотите изменить хэш 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"
}
3 голосов
/ 29 марта 2016

Еще один способ сделать это:

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}

Это время теста ...

Пока мне нравитсяпростота ответа Йорна, я не был уверен, что это было так быстро, как должно быть, тогда я увидел комментарий сельвамани:

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% окупаются со временем, так что учтите это.Несколько ответов не были включены, потому что есть потенциальные недостатки, из-за которых они могли бы дать плохие результаты.

3 голосов
/ 28 октября 2010

Точное решение будет зависеть от формата, в котором у вас есть новые ключи (или если вы можете извлечь новый ключ из старого ключа.)

Если у вас есть хеш 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
0 голосов
/ 15 июля 2017
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 голосов
/ 27 октября 2015

Если вы также беспокоитесь о производительности, это быстрее:

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

Вы не создаете новый хэш и переименовываете только необходимые ключи.Это повышает производительность.

Более подробную информацию можно найти в " Как элегантно переименовать все ключи в хэше в Ruby? "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...