Class Hash
In: lib/facets/core/facets/array/extract_options.rb
lib/facets/core/facets/object/object_state.rb
lib/facets/core/facets/kernel/blank.rb
lib/facets/core/facets/hash/symbolize_keys.rb
lib/facets/core/facets/hash/recurse.rb
lib/facets/core/facets/hash/update_values.rb
lib/facets/core/facets/hash/new_with.rb
lib/facets/core/facets/hash/subset.rb
lib/facets/core/facets/hash/op_push.rb
lib/facets/core/facets/hash/argumentize.rb
lib/facets/core/facets/hash/to_mod.rb
lib/facets/core/facets/hash/traverse.rb
lib/facets/core/facets/hash/slice.rb
lib/facets/core/facets/hash/op_add.rb
lib/facets/core/facets/hash/collate.rb
lib/facets/core/facets/hash/at.rb
lib/facets/core/facets/hash/deep_merge.rb
lib/facets/core/facets/hash/delete_values.rb
lib/facets/core/facets/hash/except.rb
lib/facets/core/facets/hash/data.rb
lib/facets/core/facets/hash/insert.rb
lib/facets/core/facets/hash/autonew.rb
lib/facets/core/facets/hash/update_keys.rb
lib/facets/core/facets/hash/zip.rb
lib/facets/core/facets/hash/rekey.rb
lib/facets/core/facets/hash/reverse_merge.rb
lib/facets/core/facets/hash/op_sub.rb
lib/facets/core/facets/hash/weave.rb
lib/facets/core/facets/hash/to_proc.rb
lib/facets/core/facets/hash/inverse.rb
lib/facets/core/facets/hash/count.rb
lib/facets/core/facets/hash/op_mul.rb
lib/facets/core/facets/hash/op_or.rb
lib/facets/core/facets/hash/to_struct.rb
lib/facets/core/facets/hash/keys.rb
lib/facets/core/facets/hash/dearray_values.rb
lib/facets/core/facets/hash/delete_at.rb
lib/facets/core/facets/hash/update_each.rb
lib/facets/core/facets/hash/join.rb
lib/facets/core/facets/hash/replace_each.rb
lib/facets/core/facets/hash/diff.rb
lib/facets/core/facets/hash/op_and.rb
lib/facets/core/facets/hash/graph.rb
lib/facets/core/facets/hash/delete_unless.rb
lib/facets/core/facets/hash/alias.rb
lib/facets/core/facets/hash/swap.rb
lib/facets/core/facets/hash/select.rb
lib/facets/core/facets/hash/recursively.rb
lib/facets/core/facets/to_hash.rb
lib/facets/core/facets/boolean.rb
Parent: Object

Methods

External Aliases

empty? -> blank?
[] -> at
  Alias for fetch for greater polymorphism with Array.
delete -> delete_at
  Polymorphic with Array#delete_at.

Public Class methods

Hash which auto initializes it‘s children.

  h = Hash.autonew
  h['s1']['p1'] = 4
  h['s1']['p2'] = 5
  h['s1']['p3'] = 2
  h['s1']['p4'] = 3

  h #=> {"s1"=>{"p1"=>4, "p4"=>3, "p3"=>2, "p2"=>5}}

  h['s1'].keys.sort
  #=> ["p1", "p2", "p3", "p4"]

CREDIT: Trans, Jan Molic

[Source]

# File lib/facets/core/facets/hash/autonew.rb, line 18
  def self.autonew(*args)
    leet = lambda{ |hsh, key| hsh[key] = new( &leet ) }
    new(*args,&leet)
  end

Instantiate a new hash with a default value determined by the block.

Hash.new_with{ [] }

CREDIT: Pit Capitan

[Source]

# File lib/facets/core/facets/hash/new_with.rb, line 10
  def self.new_with #:yield:
    new { |h, k| h[k] = yield }
  end

Creates a new hash from two separate arrays, a keys array and a values array.

  Hash.zip(["a","b","c"], [1,2,3])
  # => { "a"=>1, "b"=>2, "c"=>3 }

CREDIT: Trans, Ara T. Howard

[Source]

# File lib/facets/core/facets/hash/zip.rb, line 11
  def self.zip(keys,values) # or some better name
    h = {}
    keys.size.times{ |i| h[ keys[i] ] = values[i] }
    h
  end

Public Instance methods

Hash intersection. Two hashes intersect when their pairs are equal.

  ({:a=>1,:b=>2} & {:a=>1,:c=>3})  #=> {:a=>1}

A hash can also be intersected with an array to intersect keys only.

  ({:a=>1,:b=>2} & [:a,:c])  #=> {:a=>1}

The later form is similar to pairs_at. The differ only in that pairs_at will return a nil value for a key not in the hash, but #& will not.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_and.rb, line 19
  def &(other)
    case other
    when Array
      k = (keys & other)
      Hash[*(k.zip(values_at(*k)).flatten)]
    else
      x = (to_a & other.to_a).inject([]) do |a, kv|
        a.concat kv; a
      end
      Hash[*x]
    end
  end

Like merge operator ’+’ but merges in reverse order.

  h1 = {:a=>1}
  h2 = {:a=>2, :b=>3}

  (h1 + h2) #=> { :a=>2, :b=>3 }
  (h1 * h2)  #=> { :a=>1, :b=>3 }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_mul.rb, line 13
  def *(other)
    other.merge(self)
  end

Operator for merge.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_add.rb, line 7
  def +(other)
    merge(other)
  end

Operator for remove hash paris. If another hash is given the pairs are only removed if both key and value are equal. If an array is given then matching keys are removed.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_sub.rb, line 9
  def -(other)
    h = self.dup
    if other.respond_to?(:to_ary)
      other.to_ary.each do |k|
        h.delete(k)
      end
    else
      other.each do |k,v|
        if h.key?(k)
          h.delete(k) if v == h[k]
        end
      end
    end
    h
  end

Can be used like update, or passed as two-element [key,value] array.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_push.rb, line 8
  def <<(other)
    if other.respond_to?(:to_ary)
      self.store(*other)
    else
      update(other)
    end
    self
  end

Modifies the receiving Hash so that the value previously referred to by oldkey is also referenced by newkey; oldkey is retained in the Hash. If oldkey does not exist as a key in the Hash, no change is effected.

Returns a reference to the Hash.

  foo = { :name=>'Gavin', 'wife'=>:Lisa }
  foo.alias!('name',:name)     #=> { :name=>'Gavin', 'name'=>'Gavin', 'wife'=>:Lisa }

  foo = { :name=>'Gavin', 'wife'=>:Lisa }
  foo.alias!('spouse','wife')  #=> { :name=>'Gavin', 'wife'=>:Lisa, 'spouse'=>:Lisa }

  foo = { :name=>'Gavin', 'wife'=>:Lisa }
  foo.alias!('bar','foo')      #=> { :name=>'Gavin', 'wife'=>:Lisa }

Note that if the oldkey is reassigned, the reference will no longer exist, and the newkey will remain as it was.

CREDIT: Gavin Sinclair

TODO: Rename to aliaskey or something else.

[Source]

# File lib/facets/core/facets/hash/alias.rb, line 25
  def alias!(newkey, oldkey)
    self[newkey] = self[oldkey] if self.has_key?(oldkey)
    self
  end

Turn a hash into a method arguments.

  h = { :list => [1,2], :base => "HI" }

Without an argument field.

  h.argumentize #=> [ { :list => [1,2], :base => "HI" } ]

With an argument field.

  h.argumentize(:list)   #=> [ 1, 2, { :base => "HI" } ]
  h.argumentize(:base)   #=> [ "HI", { :list => [1,2] } ]

[Source]

# File lib/facets/core/facets/hash/argumentize.rb, line 16
  def argumentize(args_field=nil)
    config = dup
    if args_field
      args = [config.delete(args_field)].flatten.compact
    else
      args = []
    end
    args << config
    return args
  end

Merge the values of this hash with those from another, setting all values to be arrays representing the values from both hashes.

  { :a=>1, :b=>2 }.collate(:a=>3, :b=>4, :c=>5)
  #=> { :a=>[1,3], :b=>[2,4], :c=>[5] }

CREDIT: Tilo Sloboda, Gavin Kistner (Phrogz)

[Source]

# File lib/facets/core/facets/hash/collate.rb, line 11
  def collate(other)
    h = Hash.new
    (keys + other.keys).each do |key|
      h[key] = []
    end
    each do |key, value|
      h[key] << value
    end
    other.each do |key, value|
      h[key] << value
    end
    h.each{ |k,v| v.flatten! }
    h
  end

The same as collate, but modifies the receiver in place.

[Source]

# File lib/facets/core/facets/hash/collate.rb, line 27
  def collate!(other_hash)
    result = collate(other_hash)
    replace(result)
  end

Like Enumerable#count, but counts hash values.

  {:A=>1, :B=>1}.count(1) #=> 2

[Source]

# File lib/facets/core/facets/hash/count.rb, line 7
  def count(value)
    values.count(value)
  end

Access to a hash as if it were an OpenStruct.

  h = {:a=>1, :b=>2}

  h.data.a  #=> 1
  h.data.b  #=> 2
  h.data.c  #=> nil

  h.data.c = 3
  h.data.c  #=> 3

  h.data.a?  #=> true
  h.data.d?  #=> false

TODO: Change name of Hash#data to something better?

TODO: Is this really a method worth having?

[Source]

# File lib/facets/core/facets/hash/data.rb, line 22
  def data
    this = self
    Functor.new do |op, *a|
      case op.to_s
      when /\=$/
        op = op.to_s.chomp('=')
        this[op] = a.first
      when /\?$/
        op = op.to_s.chomp('?')
        this.key?(op.to_s) || this.key?(op.to_sym)
      when /\!$/
        op = op.to_s.chomp('!')
        this[op] # ???
      else
        this[op.to_s] || this[op.to_sym]
      end
    end
  end

Any array values with one or no elements will be set to the element or nil.

  h = { :a=>[1], :b=>[1,2], :c=>3, :d=>[] }
  h.dearray_singular_values  #=> { :a=>1, :b=>[1,2], :c=>3, :d=>nil }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/dearray_values.rb, line 32
  def dearray_singular_values
    h = {}
    each do |k,v|
      case v
      when Array
        h[k] = (v.size < 2) ? v[0] : v
      else
        h[k] = v
      end
    end
    h
  end

Any array values with be replaced with the first element of the array. Arrays with no elements will be set to nil.

  h = { :a=>[1], :b=>[1,2], :c=>3, :d=>[] }
  h.dearray_values  #=> { :a=>1, :b=>1, :c=>3, :d=>nil }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/dearray_values.rb, line 11
  def dearray_values(index=0)
    h = {}
    each do |k,v|
      case v
      when Array
        h[k] = v[index] || v[-1]
      else
        h[k] = v
      end
    end
    h
  end

Same as Hash#merge but recursively merges sub-hashes.

[Source]

# File lib/facets/core/facets/hash/deep_merge.rb, line 5
  def deep_merge(other)
    hash = self.dup
    other.each do |key, value|
      myval = self[key]
      if value.is_a?(Hash) && myval.is_a?(Hash)
        hash[key] = myval.deep_merge(value)
      else
        hash[key] = value
      end
    end
    hash
  end

Same as Hash#merge! but recursively merges sub-hashes.

[Source]

# File lib/facets/core/facets/hash/deep_merge.rb, line 20
  def deep_merge!(other)
    other.each do |key, value|
      myval = self[key]
      if value.is_a?(Hash) && myval.is_a?(Hash)
        myval.deep_merge!(value)
      else
        self[key] = value
      end
    end
    self
  end

Inverse of delete_if.

  h = { :a => 1, :b => 2, :c => 3 }
  r = h.delete_unless{|k,v| v == 1}
  r  #=> { :a => 1 }
  h  #=> { :a => 1 }

CREDIT: Daniel Schierbeck

[Source]

# File lib/facets/core/facets/hash/delete_unless.rb, line 12
  def delete_unless #:yield:
    delete_if{ |key, value| ! yield(key, value) }
  end

Minor modification to Ruby‘s Hash#delete method allowing it to take multiple keys.

  hsh = { :a => 1, :b => 2 }
  hsh.delete_values(1)
  hsh  #=> { :b => 2 }

Returns a list of keys of the deleted entries.

CREDIT: Daniel Schierbeck

[Source]

# File lib/facets/core/facets/hash/delete_values.rb, line 14
  def delete_values(*values)
    deleted_keys = []
    keys.each do |key|
      if values.include?(fetch(key))
        deleted_keys << key
        delete(key)
      end
    end
    deleted_keys
  end

Minor modification to Ruby‘s Hash#delete method allowing it to take multiple keys.

   hsh = {:a=>1, :b=>2, :c=>3}

   a, b, c = hsh.delete_values_at(:a, :b, :c)

   [a, b, c]  #=> [1, 2, 3]
   hsh        #=> {}

CREDIT: Daniel Schierbeck

[Source]

# File lib/facets/core/facets/hash/delete_values.rb, line 37
  def delete_values_at(*keys, &yld)
    keys.map{|key| delete(key, &yld) }
  end

Difference comparison of two hashes.

  h1 = {:a=>1,:b=>2}
  h2 = {:a=>1,:b=>3}

  h1.diff(h2)  #=> {:b=>2}
  h2.diff(h1)  #=> {:b=>3}

[Source]

# File lib/facets/core/facets/hash/diff.rb, line 11
  def diff(hash)
    h1 = self.dup.delete_if{ |k,v| hash[k] == v }
    h2 = hash.dup.delete_if{ |k,v| has_key?(k) }
    h1.merge(h2)
  end

Each with key is like each_pair but reverses the order the parameters to [value,key] instead of [key,value].

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/keys.rb, line 40
  def each_with_key( &yld )
    each_pair{ |k,v| yld.call(v,k) }
  end

Returns a new hash less the given keys.

[Source]

# File lib/facets/core/facets/hash/except.rb, line 4
  def except(*less_keys)
    hash = dup
    less_keys.each{ |k| hash.delete(k) }
    hash
  end

Replaces hash with new hash less the given keys. This returns the hash of keys removed.

  h = {:a=>1, :b=>2, :c=>3}
  h.except!(:a)  #=> {:a=>1}
  h              #=> {:b=>2,:c=>3}

Returns a Hash of the removed pairs.

[Source]

# File lib/facets/core/facets/hash/except.rb, line 18
  def except!(*rejected)
    removed = {}
    rejected.each{ |k| removed[k] = delete(k) }
    removed
  end

By default, only instances of Hash itself are extractable. Subclasses of Hash may implement this method and return true to declare themselves as extractable. If a Hash is extractable, Array#extract_options! pops it from the Array when it is the last element of the Array.

[Source]

# File lib/facets/core/facets/array/extract_options.rb, line 7
  def extractable_options?
    instance_of?(Hash)
  end

In place version of graph.

NOTE: Hash#graph! is only useful for Hash. It is not generally applicable to Enumerable.

[Source]

# File lib/facets/core/facets/hash/graph.rb, line 10
  def graph!(&yld)
    replace(graph(&yld))
  end

Returns true or false whether the hash contains the given keys.

  h = { :a => 1, :b => 2 }
  h.has_keys?( :a )   #=> true
  h.has_keys?( :c )   #=> false

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/keys.rb, line 12
  def has_keys?(*check_keys)
    unknown_keys = check_keys - self.keys
    return unknown_keys.empty?
  end

Returns true if the hash contains only the given keys, otherwise false.

  h = { :a => 1, :b => 2 }
  h.has_only_keys?( :a, :b )   #=> true
  h.has_only_keys?( :a )       #=> false

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/keys.rb, line 28
  def has_only_keys?(*check_keys)
    unknown_keys = self.keys - check_keys
    return unknown_keys.empty?
  end

As with store but only if the key isn‘t already in the hash.

TODO: Would store? be a better name?

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/insert.rb, line 10
  def insert(name, value)
    if key?(name)
      false
    else
      store(name,value)
      true
    end
  end

Create a "true" inverse hash by storing mutliple values in Arrays.

  h = {"a"=>3, "b"=>3, "c"=>3, "d"=>2, "e"=>9, "f"=>3, "g"=>9}

  h.invert           #=> {2=>"d", 3=>"f", 9=>"g"}
  h.inverse          #=> {2=>"d", 3=>["f", "c", "b", "a"], 9=>["g", "e"]}
  h.inverse.inverse  #=> {"a"=>3, "b"=>3, "c"=>3, "d"=>2, "e"=>9, "f"=>3, "g"=>9}

Of course the inverse of the inverse should be the same.

  (h.inverse.inverse == h)  #=> true

CREDIT: Tilo Sloboda

[Source]

# File lib/facets/core/facets/hash/inverse.rb, line 17
  def inverse
    i = Hash.new
    self.each_pair{ |k,v|
      if (Array === v)
        v.each{ |x| i[x] = ( i.has_key?(x) ? [k,i[x]].flatten : k ) }
      else
        i[v] = ( i.has_key?(v) ? [k,i[v]].flatten : k )
      end
    }
    return i
  end

Like Array#join but specialized to Hash.

NOTE: Without Ruby 1.9 this would be difficult to rely on becuase hashes did not have a strict order.

CREDIT: Mauricio Fernandez

[Source]

# File lib/facets/core/facets/hash/join.rb, line 10
  def join(pair_divider='', elem_divider=nil)
    elem_divider ||= pair_divider
    s = []
    each{ |k,v| s << "#{k}#{pair_divider}#{v}" }
    s.join(elem_divider)
  end
keys?(*check_keys)

Alias for has_keys?

mash!(&yld)

Alias for graph!

[Source]

# File lib/facets/core/facets/object/object_state.rb, line 61
  def object_state(data=nil)
    data ? replace(data) : dup
  end
only_keys?(*check_keys)

Alias for has_only_keys?

Apply a block to hash, and recursively apply that block to each sub-hash or types.

  h = {:a=>1, :b=>{:b1=>1, :b2=>2}}
  g = h.recurse{|h| h.inject({}){|h,(k,v)| h[k.to_s] = v; h} }
  g  #=> {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}}

[Source]

# File lib/facets/core/facets/hash/recurse.rb, line 10
  def recurse(*types, &block)
    types = [self.class] if types.empty?
    h = inject({}) do |hash, (key, value)|
      case value
      when *types
        hash[key] = value.recurse(*types, &block)
      else
        hash[key] = value
      end
      hash
    end
    yield h
  end

In place form of recurse.

[Source]

# File lib/facets/core/facets/hash/recurse.rb, line 25
  def recurse!(&block)
    replace(recurse(&block))
  end

Apply a block to a hash, and recursively apply that block to each sub-hash:

  h = {:a=>1, :b=>{:x=>1, :y=>2}}
  h.recursively.map{ |k,v| [k.to_s, v] }
  #=> [["a", 1], ["b", [["y", 2], ["x", 1]]]]

The recursive iteration can be treated separately from the non-recursive iteration by passing a block to the recursive method:

  h = {:a=>1, :b=>{:x=>1, :y=>2}}
  h.recursively{ |k,v| [k.to_s, v] }.map{ |k,v| [k.to_s, v.to_s] }
  #=> [["a", "1"], ["b", [["y", "2"], ["x", "1"]]]]

[Source]

# File lib/facets/core/facets/hash/recursively.rb, line 20
  def recursively(*types, &block)
    Recursor.new(self, *types, &block)
  end

Rekey a hash, …

  rekey()
  rekey(from_key => to_key, ...)
  rekey{|from_key| 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. If the block returns NA for a given key, then that key will be left intact.

  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.

Note that if both a key_map and a block are given, the key_map is applied first then the block.

CREDIT: Trans, Gavin Kistner

[Source]

# File lib/facets/core/facets/hash/rekey.rb, line 35
  def rekey(key_map=nil, &block)
    if !(key_map or block)
      block = lambda{|k| k.to_sym}
    end

    key_map ||= {} 

    hash = {}

    (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

    hash2 = {}

    if block
      hash.each do |k, v|
        nk = block[k]
        nk = (NA == nk ? k : nk)
        hash2[nk] = v
      end
    else
      hash2 = hash
    end

    hash2
  end

Synonym for Hash#rekey, but modifies the receiver in place (and returns it).

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

CREDIT: Trans, Gavin Kistner

[Source]

# File lib/facets/core/facets/hash/rekey.rb, line 75
  def rekey!(key_map=nil, &block)
    replace(rekey(key_map, &block))
  end

Same as update_each, but deletes the key element first.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/replace_each.rb, line 7
  def replace_each  # :yield:
    dup.each do |k,v|
      delete(k)
      update(yield(k,v))
    end
    self
  end

Allows for reverse merging where its the keys in the calling hash that wins over those in the other_hash. This is particularly useful for initializing an incoming option hash with default values:

  def setup(options = {})
    options.reverse_merge! :size => 25, :velocity => 10
  end

The default :size and :velocity is only set if the options passed in doesn‘t already have those keys set.

[Source]

# File lib/facets/core/facets/hash/reverse_merge.rb, line 15
  def reverse_merge(other)
    other.merge(self)
  end

Inplace form of reverse_merge.

[Source]

# File lib/facets/core/facets/hash/reverse_merge.rb, line 21
  def reverse_merge!(other)
    replace(reverse_merge(other))
  end
reverse_update(other)

Alias for reverse_merge!

In-place version of Hash#select. The opposite of the built-in Hash#reject!.

CREDIT: Gavin Sinclair, Noah Gibbs

[Source]

# File lib/facets/core/facets/hash/select.rb, line 10
    def select!
      reject! { |k,v| not yield(k,v) }
    end

Returns a new hash with only the given keys.

  h = {:a=>1, :b=>2}
  h.slice(:a)  #=> {:a=>1}

[Source]

# File lib/facets/core/facets/hash/slice.rb, line 8
  def slice(*keep_keys)
    hash = {}
    keep_keys.each do |key|
      hash[key] = fetch(key)
    end
    hash
  end

Replaces hash with a new hash having only the given keys. This return the hash of keys removed.

  h = {:a=>1, :b=>2}
  h.slice!(:a)  #=> {:b=>2}
  h             #=> {:a=>1}

Returns a Hash of the removed pairs.

[Source]

# File lib/facets/core/facets/hash/slice.rb, line 24
  def slice!(*keep_keys)
    rejected = keys - keep_keys
    removed = {}
    rejected.each{ |k| removed[k] = delete(k) }
    removed
  end

Return a new hash with all keys converted to strings. Converts all keys in the Hash to Strings, returning a new Hash. With a select block, limits conversion to only a certain selection of keys.

  foo = { :name=>'Gavin', :wife=>:Lisa }
  foo.stringify_keys    #=>  { "name"=>"Gavin", "wife"=>:Lisa }
  foo                   #=>  { :name =>"Gavin", :wife=>:Lisa }

This method is considered archaic. Use rekey instead.

[Source]

# File lib/facets/core/facets/hash/symbolize_keys.rb, line 61
  def stringify_keys(&select)
    dup.stringify_keys!(&select)
  end

Destructively convert all keys to strings. This is the same as Hash#stringify_keys, but modifies the receiver in place and returns it. With a select block, limits conversion to only certain keys.

  foo = { :name=>'Gavin', :wife=>:Lisa }
  foo.stringify_keys!    #=>  { "name"=>"Gavin", "wife"=>:Lisa }
  foo                    #=>  { "name"=>"Gavin", "wife"=>:Lisa }

This method is considered archaic. Use rekey instead.

[Source]

# File lib/facets/core/facets/hash/symbolize_keys.rb, line 76
  def stringify_keys!(&select)
    if select
      keys.each do |key|
        if select[key]
          self[key.to_s] = delete(key)
        end
      end
    else
      keys.each do |key|
        self[key.to_s] = delete(key)
      end
    end
    self
  end

Take a subset of the hash, based on keys given or a block that evaluates to true for each hash key.

  {'a'=>1, 'b'=>2}.subset('a')            #=> {'a'=>1}
  {'a'=>1, 'b'=>2}.subset{|k| k == 'a' }  #=> {'a'=>1}

CREDIT: Alexey Petrushin

[Source]

# File lib/facets/core/facets/hash/subset.rb, line 10
  def subset(keys=nil, &block)
    h = {}
    if keys
      self.each do |k, v|
        h[k] = v if keys.include?(k)
      end
    else
      self.each do |k, v|
        h[k] = v if block.call(k)
      end
    end
    h
  end

Swap the values of a pair of keys in place.

  {:a=>1,:b=>2}.swap!(:a,:b)  #=> {:a=>2,:b=>1}

CREDIT: Gavin Sinclair

[Source]

# File lib/facets/core/facets/hash/swap.rb, line 9
  def swap!(key1, key2)
    tmp = self[key1]
    self[key1] = self[key2]
    self[key2] = tmp
    self
  end

Return a new hash with all keys converted to symbols. With a select block, limits conversion to only a certain selection of keys.

  foo = { :name=>'Gavin', 'wife'=>:Lisa }
  foo.symbolize_keys    #=>  { :name=>"Gavin", :wife=>:Lisa }
  foo                   #=>  { :name =>"Gavin", "wife"=>:Lisa }

If the key does not respond to to_sym, then to_s will be used first.

For a more versatile method, see rekey instead.

[Source]

# File lib/facets/core/facets/hash/symbolize_keys.rb, line 18
  def symbolize_keys(&select)
    dup.symbolize_keys!(&select)
  end

Destructively convert all keys to symbols. This is the same as Hash#symbolize_keys, but modifies the receiver in place and returns it. With a select block, limits conversion to only selected keys.

  foo = { 'name'=>'Gavin', 'wife'=>:Lisa }
  foo.symbolize_keys!    #=>  { :name=>"Gavin", :wife=>:Lisa }
  foo                    #=>  { :name=>"Gavin", :wife=>:Lisa }

If the key does not respond to to_sym, then to_s will be used first.

For a more versatile method, see rekey instead.

[Source]

# File lib/facets/core/facets/hash/symbolize_keys.rb, line 34
  def symbolize_keys!(&select)
    if select
      keys.each do |key|
        if select[key]
          new_key = (key.to_sym rescue key.to_s.to_sym)
          self[new_key] = delete(key)
        end
      end       
    else
      keys.each do |key|
        new_key = (key.to_sym rescue key.to_s.to_sym)
        self[new_key] = delete(key)
      end
    end
    self
  end

Boolean conversion for not empty?

[Source]

# File lib/facets/core/facets/boolean.rb, line 117
  def to_b
    ! self.empty?
  end

Return a rehashing of self.

  {"a"=>1,"b"=>2}.to_h  #=> {"b"=>2,"a"=>1}

CREDIT: Forian Gross

[Source]

# File lib/facets/core/facets/to_hash.rb, line 211
  def to_h; rehash; end

Returns self.

[Source]

# File lib/facets/core/facets/to_hash.rb, line 215
    def to_hash; self; end

Convert a hash into a module.

  {:a=>1, :b=>2}.to_mod

Can take a block accepting key, value pairs which will be evaluated in the context of the module.

  h = {:a=>1, :b=>2}
  m = h.to_mod{ |k,v| module_function k }
  m.a #=> 1
  m.b #=> 2

CREDIT: Jay Fields

[Source]

# File lib/facets/core/facets/hash/to_mod.rb, line 20
  def to_mod(&block)
    hash = self
    Module.new do
      hash.each do |key, value|
        define_method key do
          value #.to_object
        end
        instance_exec(key, value, &block) if block
      end
    end
  end

Constructs a Proc object from a hash such that the parameter of the Proc is assigned the hash keys as attributes.

  c = Class.new do
    attr_accessor :a
  end

  h = {:a => 1}
  o = c.new
  h.to_proc.call(o)
  o.a  #=> 1

If response is set to true, then assignment will only occur if receiver responds_to? the writer method.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/to_proc.rb, line 20
  def to_proc(response=false)
    if response
      lambda do |o|
        self.each do |k,v|
          ke = "#{k}="
          o.__send__(ke, v) if respond_to?(ke)
        end
      end
    else
      lambda do |o|
        self.each do |k,v|
          ke = "#{k}="
          o.__send__(ke, v)
        end
      end
    end
  end

A method to convert a Hash into a Struct.

  h = {:name=>"Dan","age"=>33,"rank"=>"SrA","grade"=>"E4"}
  s = h.to_struct("Foo")

TODO: Is this robust enough considerd hashes aren‘t ordered?

CREDIT: Daniel Berger

[Source]

# File lib/facets/core/facets/hash/to_struct.rb, line 12
  def to_struct(struct_name)
    Struct.new(struct_name,*keys).new(*values)
  end

Returns a new hash created by traversing the hash and its subhashes, executing the given block on the key and value. The block should return a 2-element array of the form +[key, value]+.

  h = {"A"=>"A", "B"=>"B", "C"=>{"X"=>"X"}}

  g = h.traverse{ |k,v| [k.downcase, v] }

  g  #=> {"a"=>"A", "b"=>"B", "c"=>{"x"=>"X"}}

NOTE: Hash#traverse is the same as `recursive.graph` and might be deprecated in the future (if it ever works!)

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/traverse.rb, line 18
  def traverse(&block)
    inject({}) do |h,(k,v)|
      if Hash === v
        v = v.traverse(&block)
      elsif v.respond_to?(:to_hash)
        v = v.to_hash.traverse(&block)
      end
      nk, nv = block.call(k,v)
      h[nk] = nv
      h
    end
  end

In place version of traverse, which traverses the hash and its subhashes, executing the given block on the key and value.

  h = { "A"=>"A", "B"=>"B" }

  h.traverse!{ |k,v| [k.downcase, v] }

  h  #=> { "a"=>"A", "b"=>"B" }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/traverse.rb, line 42
  def traverse!(&block)
    replace(traverse(&block))
  end

Iterates through each pair and updates a the hash in place. This is formally equivalent to mash! But does not use mash to accomplish the task. Hence update_each is probably a touch faster.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/update_each.rb, line 10
  def update_each  # :yield:
    dup.each do |k,v|
     update(yield(k,v))
    end
    self
  end

Iterate over hash updating just the keys.

  h = {:a=>1, :b=>2}
  h.update_keys{ |k| "#{k}!" }
  h  #=> { "a!"=>1, "b!"=>2 }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/update_keys.rb, line 11
  def update_keys #:yield:
    if block_given?
      keys.each { |old_key| store(yield(old_key), delete(old_key)) }
    else
      to_enum(:update_keys)
    end
  end

Iterate over hash updating just the values.

  h = {:a=>1, :b=>2}
  h.update_values{ |v| v + 1 }
  h  #=> { :a=>2, :b=>3 }

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/update_values.rb, line 11
  def update_values #:yield:
    if block_given?
      each{ |k,v| store(k, yield(v)) }
    else
      to_enum(:update_values)
    end
  end

Weave is a very uniqe hash operator. I is designed to merge to complex hashes in according to sensible, regular pattern. The effect is akin to inheritance.

Two hashes are weaved together to produce a new hash. The two hashes need to be compatible according to the following rules for each node: …

  hash,   hash    => hash (recursive +)
  hash,   array   => error
  hash,   value   => error
  array,  hash    => error
  array,  array   => array + array
  array,  value   => array << value
  value,  hash    => error
  value,  array   => array.unshift(valueB)
  value1, value2  => value2

Here is a basic example:

  h1 = { :a => 1, :b => [ 1 ], :c => { :x => 1 } }
  h2 = { :a => 2, :b => [ 2 ], :c => { :x => 2 } }

  h1.weave(h2)
  #=> {:b=>[1, 2], :c=>{:x=>2}, :a=>2}

Weave follows the most expected pattern of unifying two complex hashes. It is especially useful for implementing overridable configuration schemes.

CREDIT: Thomas Sawyer

[Source]

# File lib/facets/core/facets/hash/weave.rb, line 35
  def weave(h)
    raise ArgumentError, "Hash expected" unless h.kind_of?(Hash)
    s = self.clone
    h.each { |k,node|
      node_is_hash = node.kind_of?(Hash)
      node_is_array = node.kind_of?(Array)
      if s.has_key?(k)
        self_node_is_hash = s[k].kind_of?(Hash)
        self_node_is_array = s[k].kind_of?(Array)
        if self_node_is_hash
          if node_is_hash
            s[k] = s[k].weave(node)
          elsif node_is_array
            raise ArgumentError, 'Incompatible hash addition' #self[k] = node
          else
            raise ArgumentError, 'Incompatible hash addition' #self[k] = node
          end
        elsif self_node_is_array
          if node_is_hash
            raise ArgumentError, 'Incompatible hash addition' #self[k] = node
          elsif node_is_array
            s[k] += node
          else
            s[k] << node
          end
        else
          if node_is_hash
            raise ArgumentError, 'Incompatible hash addition' #self[k] = node
          elsif node_is_array
            s[k].unshift( node )
          else
            s[k] = node
          end
        end
      else
        s[k] = node
      end
    }
    s
  end

Operator for reverse_merge.

CREDIT: Trans

[Source]

# File lib/facets/core/facets/hash/op_or.rb, line 7
  def |(other)
    other.merge(self)
  end

[Validate]