Module: Corefines::Hash::Rekey

Defined in:
lib/corefines/hash.rb

Instance Method Summary collapse

Instance Method Details

#rekey(key_map) ⇒ Hash #rekey {|key, value| ... } ⇒ Hash

Returns a new hash with keys transformed according to the given key_map or the block.

If no key_map or block is given, then all keys are converted to Symbols, as long as they respond to to_sym.

Examples:

hash = { :a => 1, 'b' => 2 }
hash.rekey(:a => :x, :c => :y) # => { :x => 1, 'b' => 2 }
hash.rekey(&:to_s) # => { 'a' => 1, 'b' => 2 }
hash.rekey { |k| k.to_s.upcase } # => { 'A' => 1, 'B' => 2 }
hash.rekey # => { :a => 1, :b => 2 }

Overloads:

  • #rekey {|key, value| ... } ⇒ Hash

    Yields:

    • (key, value)

      gives every key-value pair to the block. The return value becomes a new key.

Raises:

  • ArgumentError if both key_map and the block are given.


246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/corefines/hash.rb', line 246

module Rekey
  refine ::Hash do
    def rekey(key_map = nil, &block)
      fail ArgumentError, "provide key_map, or block, not both" if key_map && block
      block = ->(k, _) { k.to_sym rescue k } if !key_map && !block

      # Note: self.dup is used to preserve the default_proc.
      if block
        # This is needed for "symbol procs" (e.g. &:to_s).
        transform_key = block.arity.abs == 1 ? ->(k, _) { block[k] } : block

        each_with_object(dup.clear) do |(key, value), hash|
          hash[ transform_key[key, value] ] = value
        end
      else
        key_map.each_with_object(dup) do |(from, to), hash|
          hash[to] = hash.delete(from) if hash.key? from
        end
      end
    end

    def rekey!(key_map = nil, &block)
      replace rekey(key_map, &block)
    end
  end
end

#rekey!(key_map) ⇒ Hash #rekey! {|key, value| ... } ⇒ Hash

Transforms keys according to the given key_map or the block. Same as #rekey, but modifies self.

Overloads:

  • #rekey! {|key, value| ... } ⇒ Hash

    Yields:

    • (key, value)

      gives every key-value pair to the block. The return value becomes a new key.

Raises:

  • ArgumentError if both key_map and the block are given.


246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/corefines/hash.rb', line 246

module Rekey
  refine ::Hash do
    def rekey(key_map = nil, &block)
      fail ArgumentError, "provide key_map, or block, not both" if key_map && block
      block = ->(k, _) { k.to_sym rescue k } if !key_map && !block

      # Note: self.dup is used to preserve the default_proc.
      if block
        # This is needed for "symbol procs" (e.g. &:to_s).
        transform_key = block.arity.abs == 1 ? ->(k, _) { block[k] } : block

        each_with_object(dup.clear) do |(key, value), hash|
          hash[ transform_key[key, value] ] = value
        end
      else
        key_map.each_with_object(dup) do |(from, to), hash|
          hash[to] = hash.delete(from) if hash.key? from
        end
      end
    end

    def rekey!(key_map = nil, &block)
      replace rekey(key_map, &block)
    end
  end
end