Class Hash
In: lib/core/facets/blank.rb
lib/core/facets/kernel/object_state.rb
lib/core/facets/to_hash.rb
lib/core/facets/hash/swap.rb
lib/core/facets/hash/join.rb
lib/core/facets/hash/update_values.rb
lib/core/facets/hash/slice.rb
lib/core/facets/hash/op_add.rb
lib/core/facets/hash/op_sub.rb
lib/core/facets/hash/update_keys.rb
lib/core/facets/hash/inverse.rb
lib/core/facets/hash/autonew.rb
lib/core/facets/hash/to_proc.rb
lib/core/facets/hash/recursive_merge.rb
lib/core/facets/hash/select.rb
lib/core/facets/hash/to_struct.rb
lib/core/facets/hash/rekey.rb
lib/core/facets/hash/recursively.rb
lib/core/facets/hash/mash.rb
lib/core/facets/hash/alias.rb
lib/core/facets/hash/symbolize_keys.rb
lib/core/facets/hash/insert.rb
lib/core/facets/hash/diff.rb
lib/core/facets/hash/zipnew.rb
lib/core/facets/hash/except.rb
lib/core/facets/hash/keys.rb
lib/core/facets/hash/op_or.rb
lib/core/facets/hash/new_with.rb
lib/core/facets/hash/op_push.rb
lib/core/facets/hash/dearray_values.rb
lib/core/facets/hash/at.rb
lib/core/facets/hash/collate.rb
lib/core/facets/hash/merge.rb
lib/core/facets/hash/update_each.rb
lib/core/facets/hash/weave.rb
lib/core/facets/hash/delete.rb
lib/core/facets/hash/argumentize.rb
lib/core/facets/hash/traverse.rb
lib/core/facets/hash/op_and.rb
lib/core/facets/hash/op_mul.rb
lib/core/facets/hash/replace_each.rb
lib/core/facets/hash/group_by_value.rb
Parent: Object

Methods

External Aliases

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

Public Class methods

 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, Jan Molic

[Source]

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

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

Hash.new_with { [] }

CREDIT: Pit Capitan

[Source]

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

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, Ara T. Howard

[Source]

    # File lib/core/facets/hash/zipnew.rb, line 11
11:   def self.zipnew(keys,values) # or some better name
12:     h = {}
13:     keys.size.times{ |i| h[ keys[i] ] = values[i] }
14:     h
15:   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/core/facets/hash/op_and.rb, line 19
19:   def &(other)
20:     case other
21:     when Array
22:       k = (keys & other)
23:       Hash[*(k.zip(values_at(*k)).flatten)]
24:     else
25:       x = (to_a & other.to_a).inject([]) do |a, kv|
26:         a.concat kv; a
27:       end
28:       Hash[*x]
29:     end
30:   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/core/facets/hash/op_mul.rb, line 13
13:   def *(other)
14:     other.merge(self)
15:   end

Operator for merge.

CREDIT: Trans

[Source]

   # File lib/core/facets/hash/op_add.rb, line 7
7:   def +(other)
8:     merge(other)
9:   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/core/facets/hash/op_sub.rb, line 9
 9:   def -(other)
10:     h = self.dup
11:     if other.respond_to?(:to_ary)
12:       other.to_ary.each do |k|
13:         h.delete(k)
14:       end
15:     else
16:       other.each do |k,v|
17:         if h.key?(k)
18:           h.delete(k) if v == h[k]
19:         end
20:       end
21:     end
22:     h
23:   end

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

CREDIT: Trans

[Source]

    # File lib/core/facets/hash/op_push.rb, line 8
 8:   def <<(other)
 9:     if other.respond_to?(:to_ary)
10:       self.store(*other)
11:     else
12:       update(other)
13:     end
14:     self
15:   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/core/facets/hash/alias.rb, line 25
25:   def alias!(newkey, oldkey)
26:     self[newkey] = self[oldkey] if self.has_key?(oldkey)
27:     self
28:   end

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] } ]

[Source]

    # File lib/core/facets/hash/argumentize.rb, line 10
10:   def argumentize(args_field=nil)
11:     config = dup
12:     if args_field
13:       args = [config.delete(args_field)].flatten.compact
14:     else
15:       args = []
16:     end
17:     args << config
18:     return args
19:   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 CREDIT: Gavin Kistner (Phrogz)

[Source]

    # File lib/core/facets/hash/collate.rb, line 12
12:   def collate(other_hash)
13:     h = Hash.new
14:     # Prepare, ensuring every existing key is already an Array
15:     each do |key, value|
16:       if value.is_a?(Array)
17:         h[key] = value
18:       else
19:         h[key] = [value]
20:       end
21:     end
22:     # Collate with values from other_hash
23:     other_hash.each do |key, value|
24:       if h[key]
25:         if value.is_a?(Array)
26:           h[key].concat(value)
27:         else
28:           h[key] << value
29:         end
30:       elsif value.is_a?(Array)
31:         h[key] = value
32:       else
33:         h[key] = [value]
34:       end
35:     end
36:     #each{ |key, value| value.uniq! } if options[ :uniq ]
37:     h
38:   end

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

[Source]

    # File lib/core/facets/hash/collate.rb, line 42
42:   def collate!(other_hash)
43:     result = self.collate(other_hash)
44:     self.replace(result)
45:   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/core/facets/hash/dearray_values.rb, line 32
32:   def dearray_singular_values
33:     h = {}
34:     each do |k,v|
35:       case v
36:       when Array
37:         h[k] = (v.size < 2) ? v[0] : v
38:       else
39:         h[k] = v
40:       end
41:     end
42:     h
43:   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/core/facets/hash/dearray_values.rb, line 11
11:   def dearray_values(index=0)
12:     h = {}
13:     each do |k,v|
14:       case v
15:       when Array
16:         h[k] = v[index] || v[-1]
17:       else
18:         h[k] = v
19:       end
20:     end
21:     h
22:   end

Inverse of delete_if.

CREDIT: Daniel Schierbeck

[Source]

    # File lib/core/facets/hash/delete.rb, line 11
11:   def delete_unless #:yield:
12:     delete_if{ |key, value| ! yield(key, value) }
13:   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 }

CREDIT: Daniel Schierbeck

[Source]

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

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

[Source]

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

Difference comparison of two hashes.

[Source]

   # File lib/core/facets/hash/diff.rb, line 5
5:   def diff(hash)
6:     h1 = self.dup.delete_if{ |k,v| hash[k] == v }
7:     h2 = hash.dup.delete_if{ |k,v| has_key?(k) }
8:     h1.merge(h2)
9:   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/core/facets/hash/keys.rb, line 40
40:   def each_with_key( &yld )
41:     each_pair{ |k,v| yld.call(v,k) }
42:   end

Returns a new hash less the given keys.

[Source]

   # File lib/core/facets/hash/except.rb, line 5
5:   def except(*less_keys)
6:     slice(*keys - less_keys)
7:   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}

[Source]

    # File lib/core/facets/hash/except.rb, line 18
18:     def except!(*less_keys)
19:       removed = slice(*less_keys)
20:       replace(except(*less_keys))
21:       removed
22:     end
graph!(&yld)

Alias for mash!

Like group_by, but allows hash values to be grouped with weeding out the keys.

  Example:

  birthdays = {...}   # Maps each person to his/her birthday.

Now I want to have the list of people that have their birthday on a specific date. This can be done by creating a hash first, using group_by:

  birthdays.group_by{|person, birthday| birthday}

This returns:

{date=>[[person1, date], [person2, date], [person3, date]]}

… which is a bit inconvient. Too many dates. I would rather like to have:

  {date=>[person1, person2, person3]]}

This can be achieved by:

  birthdays.inject!({}){|h, (person, date)| (h[date] ||= []) << person}

I‘ve used this pattern just once too often, so I moved the code to Hash (and Enumerable, for associative arrays). Here‘s the cleaner code:

birthdays.group_by_value

  h = {"A"=>1, "B"=>1, "C"=>1, "D"=>2, "E"=>2, "F"=>2, "G"=>3, "H"=>3, "I"=>3}

  h.group_by{|k, v| v}    # ==> {1=>[["A", 1], ["B", 1], ["C", 1]], 2=>[["D", 2], ["E", 2], ["F", 2]], 3=>[["G", 3], ["H", 3], ["I", 3]]}
  h.group_by_value        # ==> {1=>["A", "B", "C"], 2=>["D", "E", "F"], 3=>["G", "H", "I"]}
  h.sort.group_by_value   # ==> [[1, ["A", "B", "C"]], [2, ["D", "E", "F"]], [3, ["G", "H", "I"]]]

CREDIT: Erik Veenstra

[Source]

    # File lib/core/facets/hash/group_by_value.rb, line 42
42:   def group_by_value
43:     res = {}
44:     each{|k, v| (res[v] ||= []) << k}
45:     res
46:   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/core/facets/hash/keys.rb, line 12
12:   def has_keys?(*check_keys)
13:     unknown_keys = check_keys - self.keys
14:     return unknown_keys.empty?
15:   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/core/facets/hash/keys.rb, line 28
28:   def has_only_keys?(*check_keys)
29:     unknown_keys = self.keys - check_keys
30:     return unknown_keys.empty?
31:   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/core/facets/hash/insert.rb, line 10
10:   def insert(name, value)
11:     if key?(name)
12:       false
13:     else
14:       store(name,value)
15:       true
16:     end
17:   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}
  h.inverse.inverse == h  #=> true

CREDIT: Tilo Sloboda

[Source]

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

Like Array#join but specialized to Hash.

CREDIT: Mauricio Fernandez

[Source]

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

Alias for has_keys?

In place version of mash.

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

[Source]

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

[Source]

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

Alias for has_only_keys?

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

[Source]

    # File lib/core/facets/hash/recursive_merge.rb, line 5
 5:   def recursive_merge(other)
 6:     hash = self.dup
 7:     other.each do |key, value|
 8:       myval = self[key]
 9:       if value.is_a?(Hash) && myval.is_a?(Hash)
10:         hash[key] = myval.recursive_merge(value)
11:       else
12:         hash[key] = value
13:       end
14:     end
15:     hash
16:   end

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

[Source]

    # File lib/core/facets/hash/recursive_merge.rb, line 20
20:   def recursive_merge!(other)
21:     other.each do |key, value|
22:       myval = self[key]
23:       if value.is_a?(Hash) && myval.is_a?(Hash)
24:         myval.recursive_merge!(value)
25:       else
26:         self[key] = value
27:       end
28:     end
29:     self
30:   end

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}}

[Source]

    # File lib/core/facets/hash/recursively.rb, line 10
10:   def recursively(&block)
11:     h = inject({}) do |hash, (key, value)|
12:       if value.is_a?(Hash)
13:         hash[key] = value.recursively(&block)
14:       else
15:         hash[key] = value
16:       end
17:       hash
18:     end
19:     yield h
20:   end

[Source]

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

Rekey a hash.

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

If no arguments or block are given, then all keys are converted to Symbols.

If two keys are given, then the second key is changed to the first. You can think of it as alias for hash keys.

  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, Gavin Kistner

[Source]

    # File lib/core/facets/hash/rekey.rb, line 32
32:   def rekey(*args, &block)
33:     dup.rekey!(*args, &block)
34:   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.inspect               #=>  { "name"=>"Gavin", "wife"=>:Lisa }

CREDIT: Trans, Gavin Kistner

[Source]

    # File lib/core/facets/hash/rekey.rb, line 44
44:   def rekey!(*args, &block)
45:     # for backward comptability (TODO: DEPRECATE).
46:     block = args.pop.to_sym.to_proc if args.size == 1
47:     # if no args use block.
48:     if args.empty?
49:       block = lambda{|k| k.to_sym} unless block
50:       keys.each do |k|
51:         nk = block[k]
52:         self[nk]=delete(k) if nk
53:       end
54:     else
55:       raise ArgumentError, "3 for 2" if block
56:       to, from = *args
57:       self[to] = self.delete(from) if self.has_key?(from)
58:     end
59:     self
60:   end

Same as update_each, but deletes the key element first.

CREDIT: Trans

[Source]

    # File lib/core/facets/hash/replace_each.rb, line 7
 7:   def replace_each  # :yield:
 8:     dup.each do |k,v|
 9:       delete(k)
10:       update(yield(k,v))
11:     end
12:     self
13:   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/core/facets/hash/merge.rb, line 15
15:   def reverse_merge(other)
16:     other.merge(self)
17:   end

Inplace form of reverse_merge.

[Source]

    # File lib/core/facets/hash/merge.rb, line 21
21:   def reverse_merge!(other)
22:     replace(reverse_merge(other))
23:   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/core/facets/hash/select.rb, line 8
 8:   def select!
 9:     reject! { |k,v| not yield(k,v) }
10:   end

Returns a new hash with only the given keys.

[Source]

    # File lib/core/facets/hash/slice.rb, line 9
 9:     def slice(*keep_keys)
10:       h = {}
11:       keep_keys.each do |key|
12:         h[key] = fetch(key)
13:       end
14:       h
15:     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)  #=> {:a=>1}
  h             #=> {:b=>2}

[Source]

    # File lib/core/facets/hash/slice.rb, line 24
24:     def slice!(*keep_keys)
25:       removed = except(*keep_keys)
26:       replace(slice(*keep_keys))
27:       removed
28:     end

Converts all keys in the Hash to Strings, returning a new Hash. With a filter parameter, limits conversion to only a certain selection of keys.

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

This method is considered archaic. Use rekey instead.

[Source]

    # File lib/core/facets/hash/symbolize_keys.rb, line 54
54:     def stringify_keys(&filter)
55:       if filter
56:         rekey{ |k| filter[k] ? k.to_s : nil }
57:       else
58:         rekey{ |k| k.to_s }
59:       end
60:     end

Synonym for Hash#stringify_keys, but modifies the receiver in place and returns it. With a filter parameter, limits conversion to only a certain selection of keys.

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

This method is considered archaic. Use rekey instead.

[Source]

    # File lib/core/facets/hash/symbolize_keys.rb, line 73
73:     def stringify_keys!(&filter)
74:       if filter
75:         rekey!{ |k| filter[k] ? k.to_s : nil }
76:       else
77:         rekey!{ |k| k.to_s }
78:       end
79:     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/core/facets/hash/swap.rb, line 9
 9:   def swap!(key1, key2)
10:     tmp = self[key1]
11:     self[key1] = self[key2]
12:     self[key2] = tmp
13:     self
14:   end

Converts all keys in the Hash to Symbols, returning a new Hash. With a filter, limits conversion to only a certain selection of keys.

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

This method is considered archaic. Use rekey instead.

[Source]

    # File lib/core/facets/hash/symbolize_keys.rb, line 20
20:     def symbolize_keys(&filter)
21:       if filter
22:         rekey{ |k| filter[k] ? k.to_sym : nil }
23:       else
24:         rekey{ |k| k.to_sym }
25:       end
26:     end

Synonym for Hash#symbolize_keys, but modifies the receiver in place and returns it. With a filter parameter, limits conversion to only a certain selection of keys.

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

This method is considered archaic. Use rekey instead.

[Source]

    # File lib/core/facets/hash/symbolize_keys.rb, line 37
37:     def symbolize_keys!(&filter)
38:       if filter
39:         rekey!{ |k| filter[k] ? k.to_sym : nil }
40:       else
41:         rekey!{ |k| k.to_sym }
42:       end
43:     end

Return a rehashing of self.

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

CREDIT: Forian Gross

[Source]

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

Returns self.

CREDIT: Trans

[Source]

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

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

[Source]

    # File lib/core/facets/hash/to_proc.rb, line 15
15:   def to_proc
16:     lambda do |o|
17:       self.each do |k,v|
18:         ke = "#{k}="
19:         o.__send__(ke, v)
20:       end
21:     end
22:   end

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

[Source]

    # File lib/core/facets/hash/to_proc.rb, line 31
31:   def to_proc_with_reponse
32:     lambda do |o|
33:       self.each do |k,v|
34:         ke = "#{k}="
35:         o.__send__(ke, v) if respond_to?(ke)
36:       end
37:     end
38:   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/core/facets/hash/to_struct.rb, line 12
12:   def to_struct(struct_name)
13:     Struct.new(struct_name,*keys).new(*values)
14:   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" }
  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

[Source]

    # File lib/core/facets/hash/traverse.rb, line 18
18:   def traverse(&b)
19:     inject({}) do |h,(k,v)|
20:       v = ( Hash === v ? v.traverse(&b) : v )
21:       nk, nv = b[k,v]
22:       h[nk] = nv #( Hash === v ? v.traverse(base,&b) : nv )
23:       h
24:     end
25:   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/core/facets/hash/traverse.rb, line 36
36:   def traverse!(&b)
37:     self.replace( self.traverse(&b) )
38:   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/core/facets/hash/update_each.rb, line 10
10:   def update_each  # :yield:
11:     dup.each do |k,v|
12:      update(yield(k,v))
13:     end
14:     self
15:   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/core/facets/hash/update_keys.rb, line 11
11:   def update_keys #:yield:
12:     if block_given?
13:       keys.each { |old_key| store(yield(old_key), delete(old_key)) }
14:     else
15:       to_enum(:update_keys)
16:     end
17:   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/core/facets/hash/update_values.rb, line 11
11:   def update_values #:yield:
12:     if block_given?
13:       each{ |k,v| store(k, yield(v)) }
14:     else
15:       to_enum(:update_values)
16:     end
17:   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:

  <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

[Source]

    # File lib/core/facets/hash/weave.rb, line 40
40:   def weave(h)
41:     raise ArgumentError, "Hash expected" unless h.kind_of?(Hash)
42:     s = self.clone
43:     h.each { |k,node|
44:       node_is_hash = node.kind_of?(Hash)
45:       node_is_array = node.kind_of?(Array)
46:       if s.has_key?(k)
47:         self_node_is_hash = s[k].kind_of?(Hash)
48:         self_node_is_array = s[k].kind_of?(Array)
49:         if self_node_is_hash
50:           if node_is_hash
51:             s[k] = s[k].weave(node)
52:           elsif node_is_array
53:             raise ArgumentError, 'Incompatible hash addition' #self[k] = node
54:           else
55:             raise ArgumentError, 'Incompatible hash addition' #self[k] = node
56:           end
57:         elsif self_node_is_array
58:           if node_is_hash
59:             raise ArgumentError, 'Incompatible hash addition' #self[k] = node
60:           elsif node_is_array
61:             s[k] += node
62:           else
63:             s[k] << node
64:           end
65:         else
66:           if node_is_hash
67:             raise ArgumentError, 'Incompatible hash addition' #self[k] = node
68:           elsif node_is_array
69:             s[k].unshift( node )
70:           else
71:             s[k] = node
72:           end
73:         end
74:       else
75:         s[k] = node
76:       end
77:     }
78:     s
79:   end

Operator for reverse_merge.

CREDIT: Trans

[Source]

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

[Validate]