How to change all the keys of a hash by a new set of given keys

后端 未结 7 1422
广开言路
广开言路 2020-12-04 19:04

How do I change all the keys of a hash by a new set of given keys?

Is there a way to do that elegantly?

7条回答
  •  無奈伤痛
    2020-12-04 19:58

    Another way to do it is:

    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}
    

    Breaking it down:

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

    It's benchmark time...

    While I like the simplicity of Jörn's answer, I'm wasn't sure it was as fast as it should be, then I saw selvamani's comment:

    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%
    

    These are running very close together speed wise, so any will do, but 39% pays off over time so consider that. A couple answers were not included because there are potential flaws where they'd return bad results.

提交回复
热议问题