Methods
Public Class methods
autonew(*args)

Hash which auto initializes it‘s children.

 ah = Hash.autonew
 ah['section one']['param one'] = 4
 ah['section one']['param two'] = 5
 ah['section one']['param three'] = 2
 ah['section one']['param four'] = 3

 p ah
 # {"section one"=>{"param one"=>4, "param four"=>3, "param three"=>2, "param two"=>5}}

 p ah['section one'].keys
 # ["param one", "param four", "param three", "param two"]

CREDIT: Trans CREDIT: Jan Molic

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

Hash which auto initializes it‘s children.

 ah = Hash.autonew
 ah['section one']['param one'] = 4
 ah['section one']['param two'] = 5
 ah['section one']['param three'] = 2
 ah['section one']['param four'] = 3

 p ah
 # {"section one"=>{"param one"=>4, "param four"=>3, "param three"=>2, "param two"=>5}}

 p ah['section one'].keys
 # ["param one", "param four", "param three", "param two"]

CREDIT: Trans CREDIT: Jan Molic

# File lib/core/facets/hash/autonew.rb, line 20
  def self.autonew(*args)
    #new(*args){|a,k| a[k] = self.class::new(*args)}
    leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
    new(*args,&leet)
  end
zipnew(keys,values)

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

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

 CREDIT: Trans
 CREDIT: Ara T. Howard
# File lib/core/facets/hash/autonew.rb, line 35
  def self.zipnew(keys,values) # or some better name
    h = {}
    keys.size.times{ |i| h[ keys[i] ] = values[i] }
    h
  end
zipnew(keys,values)

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

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

 CREDIT: Trans
 CREDIT: Ara T. Howard
# File lib/core/facets/hash/autonew.rb, line 35
  def self.zipnew(keys,values) # or some better name
    h = {}
    keys.size.times{ |i| h[ keys[i] ] = values[i] }
    h
  end
Public Instance methods
&(other)

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
# File lib/core/facets/hash/op.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
&(other)

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
# File lib/core/facets/hash/op.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
*(other)

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
# File lib/core/facets/hash/op.rb, line 80
  def *(other)
    other.merge(self)
  end
*(other)

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
# File lib/core/facets/hash/op.rb, line 80
  def *(other)
    other.merge(self)
  end
+(other)

Operator for merge.

  CREDIT: Trans
# File lib/core/facets/hash/op.rb, line 44
  def +(other)
    merge(other)
  end
+(other)

Operator for merge.

  CREDIT: Trans
# File lib/core/facets/hash/op.rb, line 44
  def +(other)
    merge(other)
  end
-(other)

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
# File lib/core/facets/hash/op.rb, line 54
  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
-(other)

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
# File lib/core/facets/hash/op.rb, line 54
  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
<<(other)

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

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

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

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

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.

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

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.

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

Turn a hash into arguments.

  h = { :list => [1,2], :base => "HI" }
  h.argumentize #=> [ [], { :list => [1,2], :base => "HI" } ]
  h.argumentize(:list)   #=> [ [1,2], { :base => "HI" } ]
  h.argumentize(:base)   #=> [ ["HI"], { :list => [1,2] } ]
# File lib/core/facets/hash/argumentize.rb, line 10
  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
argumentize(args_field=nil)

Turn a hash into arguments.

  h = { :list => [1,2], :base => "HI" }
  h.argumentize #=> [ [], { :list => [1,2], :base => "HI" } ]
  h.argumentize(:list)   #=> [ [1,2], { :base => "HI" } ]
  h.argumentize(:base)   #=> [ ["HI"], { :list => [1,2] } ]
# File lib/core/facets/hash/argumentize.rb, line 10
  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
collate(other_hash)

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: Gavin Kistner (Phrogz)
# File lib/core/facets/hash/collate.rb, line 11
  def collate(other_hash)
    dup.collate!(other_hash)
  end
collate(other_hash)

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: Gavin Kistner (Phrogz)
# File lib/core/facets/hash/collate.rb, line 11
  def collate(other_hash)
    dup.collate!(other_hash)
  end
collate!(other_hash)

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

# File lib/core/facets/hash/collate.rb, line 17
  def collate!(other_hash)
    # Prepare, ensuring every existing key is already an Array
    each do |key, value|
      if value.is_a?(Array)
        self[key] = value
      else
        self[key] = [value]
      end
    end
    # Collate with values from other_hash
    other_hash.each do |key, value|
      if self[key]
        if value.is_a?(Array)
          self[key].concat( value )
        else
          self[key] << value
        end
      elsif value.is_a?(Array)
        self[key] = value
      else
        self[key] = [value]
      end
    end
    #each{ |key, value| value.uniq! } if options[ :uniq ]
    self
  end
collate!(other_hash)

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

# File lib/core/facets/hash/collate.rb, line 17
  def collate!(other_hash)
    # Prepare, ensuring every existing key is already an Array
    each do |key, value|
      if value.is_a?(Array)
        self[key] = value
      else
        self[key] = [value]
      end
    end
    # Collate with values from other_hash
    other_hash.each do |key, value|
      if self[key]
        if value.is_a?(Array)
          self[key].concat( value )
        else
          self[key] << value
        end
      elsif value.is_a?(Array)
        self[key] = value
      else
        self[key] = [value]
      end
    end
    #each{ |key, value| value.uniq! } if options[ :uniq ]
    self
  end
delete_unless( {|| ...}

Inverse of delete_if.

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

Inverse of delete_if.

  CREDIT: Daniel Schierbeck
# File lib/core/facets/hash/delete.rb, line 11
  def delete_unless #:yield:
    delete_if{ |key, value| ! yield(key, value) }
  end
delete_values(*values)

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 }

  CREDIT: Daniel Schierbeck
# File lib/core/facets/hash/delete.rb, line 24
  def delete_values(*values)
    keys.map{ |key| delete(key) if values.include?(fetch(key)) }
  end
delete_values(*values)

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 }

  CREDIT: Daniel Schierbeck
# File lib/core/facets/hash/delete.rb, line 24
  def delete_values(*values)
    keys.map{ |key| delete(key) if values.include?(fetch(key)) }
  end
delete_values_at(*keys, &yld)

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

This works niely with hash#[] and Hash#[]= facets.

   hsh[:a, :b, :c] = 1, 2, 3

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

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

  CREDIT: Daniel Schierbeck
# File lib/core/facets/hash/delete.rb, line 42
  def delete_values_at(*keys, &yld)
    keys.map{|key| delete(key, &yld) }
  end
delete_values_at(*keys, &yld)

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

This works niely with hash#[] and Hash#[]= facets.

   hsh[:a, :b, :c] = 1, 2, 3

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

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

  CREDIT: Daniel Schierbeck
# File lib/core/facets/hash/delete.rb, line 42
  def delete_values_at(*keys, &yld)
    keys.map{|key| delete(key, &yld) }
  end
diff(hash)

Difference comparison of two hashes.

# File lib/core/facets/hash/diff.rb, line 5
  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
diff(hash)

Difference comparison of two hashes.

# File lib/core/facets/hash/diff.rb, line 5
  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( &yld )

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

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

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

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

Returns a new hash less the given keys.

# File lib/core/facets/hash/except.rb, line 5
  def except(*less_keys)
    slice(*keys - less_keys)
  end
except(*less_keys)

Returns a new hash less the given keys.

# File lib/core/facets/hash/except.rb, line 5
  def except(*less_keys)
    slice(*keys - less_keys)
  end
except!(*less_keys)

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}
# File lib/core/facets/hash/except.rb, line 16
  def except!(*less_keys)
    removed = slice(*less_keys)
    replace(except(*less_keys))
    removed
  end
except!(*less_keys)

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}
# File lib/core/facets/hash/except.rb, line 16
  def except!(*less_keys)
    removed = slice(*less_keys)
    replace(except(*less_keys))
    removed
  end
graph!(&yld)

Alias for mash!

graph!(&yld)

Alias for mash!

has_keys?(*check_keys)

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
# File lib/core/facets/hash/keys.rb, line 12
  def has_keys?(*check_keys)
    unknown_keys = check_keys - self.keys
    return unknown_keys.empty?
  end
has_keys?(*check_keys)

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
This method is also aliased as keys? keys?
# File lib/core/facets/hash/keys.rb, line 12
  def has_keys?(*check_keys)
    unknown_keys = check_keys - self.keys
    return unknown_keys.empty?
  end
has_only_keys?(*check_keys)

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
This method is also aliased as only_keys? only_keys?
# File lib/core/facets/hash/keys.rb, line 28
  def has_only_keys?(*check_keys)
    unknown_keys = self.keys - check_keys
    return unknown_keys.empty?
  end
has_only_keys?(*check_keys)

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
# File lib/core/facets/hash/keys.rb, line 28
  def has_only_keys?(*check_keys)
    unknown_keys = self.keys - check_keys
    return unknown_keys.empty?
  end
insert(name, value)

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

TODO: Would store? be a better name?

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

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

TODO: Would store? be a better name?

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

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}
  h.inverse.inverse == h  #=> true

  CREDIT: Tilo Sloboda
# File lib/core/facets/hash/inverse.rb, line 14
  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
inverse()

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}
  h.inverse.inverse == h  #=> true

  CREDIT: Tilo Sloboda
# File lib/core/facets/hash/inverse.rb, line 14
  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
join(pair_divider='', elem_divider='')

Like Array#join but specialized to Hash.

 CREDIT: Mauricio Fernandez
# File lib/core/facets/hash/join.rb, line 7
  def join(pair_divider='', elem_divider='')
    s = []
    each_pair { |k,v| s << "#{k}#{pair_divider}#{v}" }
    s.join(elem_divider)
  end
join(pair_divider='', elem_divider='')

Like Array#join but specialized to Hash.

 CREDIT: Mauricio Fernandez
# File lib/core/facets/hash/join.rb, line 7
  def join(pair_divider='', elem_divider='')
    s = []
    each_pair { |k,v| s << "#{k}#{pair_divider}#{v}" }
    s.join(elem_divider)
  end
keys?(*check_keys)

Alias for has_keys?

keys?(*check_keys)

Alias for has_keys?

mash!(&yld)

In place version of mash.

  NOTE: Hash#mash! is only useful for Hash. It is not generally
        applicable to Enumerable.
# File lib/core/facets/hash/mash.rb, line 10
  def mash!(&yld)
    replace(mash(&yld))
  end
mash!(&yld)

In place version of mash.

  NOTE: Hash#mash! is only useful for Hash. It is not generally
        applicable to Enumerable.
This method is also aliased as graph! graph!
# File lib/core/facets/hash/mash.rb, line 10
  def mash!(&yld)
    replace(mash(&yld))
  end
only_keys?(*check_keys)

Alias for has_only_keys?

only_keys?(*check_keys)

Alias for has_only_keys?

recursive_merge(other)

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

# File lib/core/facets/hash/recursive_merge.rb, line 5
  def recursive_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.recursive_merge(value)
      else
        hash[key] = value
      end
    end
    hash
  end
recursive_merge(other)

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

# File lib/core/facets/hash/recursive_merge.rb, line 5
  def recursive_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.recursive_merge(value)
      else
        hash[key] = value
      end
    end
    hash
  end
recursive_merge!(other)

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

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

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

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

Apply a block to hash, and recursively apply that block to each subhash.

  h = {:a=>1, :b=>{:b1=>1, :b2=>2}}
  h.recursively{|h| h.rekey(&:to_s) }
  => {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}}
# File lib/core/facets/hash/recursively.rb, line 10
  def recursively(&block)
    h = inject({}) do |hash, (key, value)|
      if value.is_a?(Hash)
        hash[key] = value.recursively(&block)
      else
        hash[key] = value
      end
      hash
    end
    yield h
  end
recursively() {|h| ...}

Apply a block to hash, and recursively apply that block to each subhash.

  h = {:a=>1, :b=>{:b1=>1, :b2=>2}}
  h.recursively{|h| h.rekey(&:to_s) }
  => {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}}
# File lib/core/facets/hash/recursively.rb, line 10
  def recursively(&block)
    h = inject({}) do |hash, (key, value)|
      if value.is_a?(Hash)
        hash[key] = value.recursively(&block)
      else
        hash[key] = value
      end
      hash
    end
    yield h
  end
recursively!(&block)
# File lib/core/facets/hash/recursively.rb, line 24
  def recursively!(&block)
    replace(recursively(&block))
  end
recursively!(&block)
# File lib/core/facets/hash/recursively.rb, line 24
  def recursively!(&block)
    replace(recursively(&block))
  end
rekey(*args, &block)

rekey(to_key, from_key) rekey{ |key| … }

If two keys are given, then the second key is changed to the first.

  foo = { :a=>1, :b=>2 }
  foo.rekey('a',:a)       #=> { 'a'=>1, :b=>2 }
  foo.rekey('b',:b)       #=> { 'a'=>1, 'b'=>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. If the block returns nil for 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.inspect              #=>  { :name =>"Gavin", :wife=>:Lisa }

 CREDIT: Trans
 CREDIT: Gavin Kistner
# File lib/core/facets/hash/rekey.rb, line 27
  def rekey(*args, &block)
    dup.rekey!(*args, &block)
  end
rekey(*args, &block)

rekey(to_key, from_key) rekey{ |key| … }

If two keys are given, then the second key is changed to the first.

  foo = { :a=>1, :b=>2 }
  foo.rekey('a',:a)       #=> { 'a'=>1, :b=>2 }
  foo.rekey('b',:b)       #=> { 'a'=>1, 'b'=>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. If the block returns nil for 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.inspect              #=>  { :name =>"Gavin", :wife=>:Lisa }

 CREDIT: Trans
 CREDIT: Gavin Kistner
# File lib/core/facets/hash/rekey.rb, line 27
  def rekey(*args, &block)
    dup.rekey!(*args, &block)
  end
rekey!(*args, &block)

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.inspect               #=>  { "name"=>"Gavin", "wife"=>:Lisa }

 CREDIT: Trans
 CREDIT: Gavin Kistner
# File lib/core/facets/hash/rekey.rb, line 40
  def rekey!(*args, &block)
    # for backward comptability (TODO: DEPRECATE).
    block = args.pop.to_sym.to_proc if args.size == 1
    # if no args use block.
    if args.empty?
      block = lambda{|k| k.to_sym} unless block
      keys.each do |k|
        nk = block[k]
        self[nk]=delete(k) if nk
      end
    else
      raise ArgumentError, "3 for 2" if block
      to, from = *args
      self[to] = self.delete(from) if self.has_key?(from)
    end
    self
  end
rekey!(*args, &block)

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.inspect               #=>  { "name"=>"Gavin", "wife"=>:Lisa }

 CREDIT: Trans
 CREDIT: Gavin Kistner
# File lib/core/facets/hash/rekey.rb, line 40
  def rekey!(*args, &block)
    # for backward comptability (TODO: DEPRECATE).
    block = args.pop.to_sym.to_proc if args.size == 1
    # if no args use block.
    if args.empty?
      block = lambda{|k| k.to_sym} unless block
      keys.each do |k|
        nk = block[k]
        self[nk]=delete(k) if nk
      end
    else
      raise ArgumentError, "3 for 2" if block
      to, from = *args
      self[to] = self.delete(from) if self.has_key?(from)
    end
    self
  end
replace_each( {|| ...}

Same as update_each, but deletes the key element first.

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

Same as update_each, but deletes the key element first.

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

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.

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

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.

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

Inplace form of reverse_merge.

This method is also aliased as reverse_update reverse_update
# File lib/core/facets/hash/merge.rb, line 21
  def reverse_merge!(other)
    replace(reverse_merge(other))
  end
reverse_merge!(other)

Inplace form of reverse_merge.

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

Alias for reverse_merge!

reverse_update(other)

Alias for reverse_merge!

select!() {|k,v| ...}

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

  CREDIT Gavin Sinclair
  CREDIT Noah Gibbs
# File lib/core/facets/hash/select.rb, line 9
  def select!
    reject! { |k,v| not yield(k,v) }
  end
select!() {|k,v| ...}

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

  CREDIT Gavin Sinclair
  CREDIT Noah Gibbs
# File lib/core/facets/hash/select.rb, line 9
  def select!
    reject! { |k,v| not yield(k,v) }
  end
slice(*keep_keys)

Returns a new hash with only the given keys.

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

Returns a new hash with only the given keys.

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

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

# File lib/core/facets/hash/slice.rb, line 18
  def slice!(*keep_keys)
    removed = except(*keep_keys)
    replace(slice(*keep_keys))
    removed
  end
slice!(*keep_keys)

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

# File lib/core/facets/hash/slice.rb, line 18
  def slice!(*keep_keys)
    removed = except(*keep_keys)
    replace(slice(*keep_keys))
    removed
  end
swap!(key1, key2)

Swap the values of a pair of keys in place.

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

CREDIT: Gavin Sinclair

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

Swap the values of a pair of keys in place.

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

CREDIT: Gavin Sinclair

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

Return a rehashing of self.

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

CREDIT: Forian Gross

# File lib/core/facets/to_hash.rb, line 54
  def to_h; rehash; end
to_proc()

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

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

CREDIT: Trans

# File lib/core/facets/hash/to_proc.rb, line 15
  def to_proc
    lambda do |o|
      self.each do |k,v|
        ke = "#{k}="
        o.__send__(ke, v)
      end
    end
  end
to_proc()

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

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

CREDIT: Trans

# File lib/core/facets/hash/to_proc.rb, line 15
  def to_proc
    lambda do |o|
      self.each do |k,v|
        ke = "#{k}="
        o.__send__(ke, v)
      end
    end
  end
to_proc_with_reponse()

A fault-tolerent version of to_proc.

It works just like to_proc, but the block will make sure# the object responds to the assignment.

CREDIT: Trans

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

A fault-tolerent version of to_proc.

It works just like to_proc, but the block will make sure# the object responds to the assignment.

CREDIT: Trans

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

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
# File lib/core/facets/hash/to_struct.rb, line 12
  def to_struct(struct_name)
    Struct.new(struct_name,*keys).new(*values)
  end
to_struct(struct_name)

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
# File lib/core/facets/hash/to_struct.rb, line 12
  def to_struct(struct_name)
    Struct.new(struct_name,*keys).new(*values)
  end
traverse(&b)

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" }
  g = h.traverse { |k,v| [k.downcase, v] }
  g  #=> { "a"=>"A", "b"=>"B" }

TODO: Contrast these to recursibely —we may not need both.

TODO: Testing value to see if it is a Hash also catches subclasses of Hash.

      This is probably not the right thing to do and should catch Hashes only (?)

 CREDIT: Trans
# File lib/core/facets/hash/traverse.rb, line 18
  def traverse(&b)
    inject({}) do |h,(k,v)|
      v = ( Hash === v ? v.traverse(&b) : v )
      nk, nv = b[k,v]
      h[nk] = nv #( Hash === v ? v.traverse(base,&b) : nv )
      h
    end
  end
traverse(&b)

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" }
  g = h.traverse { |k,v| [k.downcase, v] }
  g  #=> { "a"=>"A", "b"=>"B" }

TODO: Contrast these to recursibely —we may not need both.

TODO: Testing value to see if it is a Hash also catches subclasses of Hash.

      This is probably not the right thing to do and should catch Hashes only (?)

 CREDIT: Trans
# File lib/core/facets/hash/traverse.rb, line 18
  def traverse(&b)
    inject({}) do |h,(k,v)|
      v = ( Hash === v ? v.traverse(&b) : v )
      nk, nv = b[k,v]
      h[nk] = nv #( Hash === v ? v.traverse(base,&b) : nv )
      h
    end
  end
traverse!(&b)

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
# File lib/core/facets/hash/traverse.rb, line 36
  def traverse!(&b)
    self.replace( self.traverse(&b) )
  end
traverse!(&b)

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
# File lib/core/facets/hash/traverse.rb, line 36
  def traverse!(&b)
    self.replace( self.traverse(&b) )
  end
update_each( {|| ...}

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
# File lib/core/facets/hash/update.rb, line 23
  def update_each  # :yield:
    dup.each do |k,v|
     update(yield(k,v))
    end
    self
  end
update_each( {|| ...}

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
# File lib/core/facets/hash/update.rb, line 23
  def update_each  # :yield:
    dup.each do |k,v|
     update(yield(k,v))
    end
    self
  end
update_keys( {|| ...}

Iterate over hash updating just the keys.

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

 CREDIT: Trans
# File lib/core/facets/hash/update.rb, line 38
  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
update_keys( {|| ...}

Iterate over hash updating just the keys.

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

 CREDIT: Trans
# File lib/core/facets/hash/update.rb, line 38
  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
update_values( {|| ...}

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
# File lib/core/facets/hash/update.rb, line 54
  def update_values #:yield:
    if block_given?
      each{ |k,v| store(k, yield(v)) }
    else
      to_enum(:update_values)
    end
  end
update_values( {|| ...}

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
# File lib/core/facets/hash/update.rb, line 54
  def update_values #:yield:
    if block_given?
      each{ |k,v| store(k, yield(v)) }
    else
      to_enum(:update_values)
    end
  end
weave(h)

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:

  <tt>
  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
  </tt>

Here is a basic example:

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

  h2 = { :a => 2, :b => [ 2 ], :c => { :x => 2 } }
  => {:b=>[2], :c=>{:x=>2}, :a=>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
# File lib/core/facets/hash/weave.rb, line 40
  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
weave(h)

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:

  <tt>
  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
  </tt>

Here is a basic example:

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

  h2 = { :a => 2, :b => [ 2 ], :c => { :x => 2 } }
  => {:b=>[2], :c=>{:x=>2}, :a=>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
# File lib/core/facets/hash/weave.rb, line 40
  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
|(other)

Operator for reverse_merge.

  CREDIT: Trans
# File lib/core/facets/hash/op.rb, line 36
  def |(other)
    other.merge(self)
  end
|(other)

Operator for reverse_merge.

  CREDIT: Trans
# File lib/core/facets/hash/op.rb, line 36
  def |(other)
    other.merge(self)
  end