Method: Hash#rekey

Defined in:
lib/dm_ruby_extensions/extend_hash.rb

#rekey(key_map = nil, &block) ⇒ Object

Borrowed from github.com/rubyworks/facets


Rekey a hash:

rekey()
rekey(from_key => to_key, ...)
rekey{|from_key| to_key}
rekey{|from_key, value| to_key}

If a key map is given, then the first key is changed to the second key.

foo = { :a=>1, :b=>2 }
foo.rekey(:a=>'a')       #=> { 'a'=>1, :b=>2 }
foo.rekey(:b=>:x)        #=> { :a =>1, :x=>2 }
foo.rekey('foo'=>'bar')  #=> { :a =>1, :b=>2 }

If a block is given, converts all keys in the Hash accroding to the given block procedure.

foo = { :name=>'Gavin', :wife=>:Lisa }
foo.rekey{ |k| k.to_s }  #=>  { "name"=>"Gavin", "wife"=>:Lisa }
foo                      #=>  { :name =>"Gavin", :wife=>:Lisa }

If no key map or block is given, then all keys are converted to Symbols.

Raises an ArgumentError if both a key_map and a block are given. If both are needed just call #rekey twice.

TODO: If nil is returned by block should the key be set to nil or the orignal key?

CREDIT: Trans, Gavin Kistner

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/dm_ruby_extensions/extend_hash.rb', line 62

def rekey(key_map=nil, &block)
  raise ArgumentError, "argument or block" if key_map && block

  if !(key_map or block)
    block = lambda{|k| k.to_sym}
  end

  if block
    hash = dup.clear
    if block.arity.abs == 1
      each_pair do |k, v|
        hash[block[k]] = v     #hash[block[k] || k] = v
      end
    else
      each_pair do |k, v|
        hash[block[k,v]] = v   #hash[block[k,v] || k] = v
      end
    end
  else
    #hash = dup.clear  # to keep default_proc
    #(keys - key_map.keys).each do |key|
    #  hash[key] = self[key]
    #end
    #key_map.each do |from, to|
    #  hash[to] = self[from] if key?(from)
    #end
    hash = dup  # to keep default_proc
    key_map.each_pair do |from, to|
      hash[to] = hash.delete(from) if hash.key?(from)
    end
  end

  hash
end