Class: Hash

Inherits:
Object show all
Defined in:
lib/more/facets/random.rb,
lib/core/facets/hash/at.rb,
lib/core/facets/hash/op.rb,
lib/more/facets/command.rb,
lib/more/facets/ostruct.rb,
lib/core/facets/hash/new.rb,
lib/more/facets/snapshot.rb,
lib/core/facets/conversion.rb,
lib/core/facets/hash/merge.rb,
lib/core/facets/hash/rekey.rb,
lib/core/facets/hash/slice.rb,
lib/core/facets/hash/weave.rb,
lib/more/facets/openobject.rb,
lib/core/facets/hash/delete.rb,
lib/core/facets/hash/insert.rb,
lib/core/facets/hash/keyize.rb,
lib/core/facets/hash/select.rb,
lib/core/facets/hash/update.rb,
lib/core/facets/hash/inverse.rb,
lib/core/facets/hash/iterate.rb,
lib/core/facets/hash/has_keys.rb,
lib/core/facets/hash/traverse.rb,
lib/core/facets/enumerable/mash.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.autonew(*args) ⇒ Object

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


20
21
22
23
24
# File 'lib/core/facets/hash/new.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) ⇒ Object

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


35
36
37
38
39
# File 'lib/core/facets/hash/new.rb', line 35

def self.zipnew(keys,values) # or some better name
  h = {}
  keys.size.times{ |i| h[ keys[i] ] = values[i] }
  h
end

Instance Method Details

#&(other) ⇒ Object

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


32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/core/facets/hash/op.rb', line 32

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) ⇒ Object

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


93
94
95
# File 'lib/core/facets/hash/op.rb', line 93

def *(other)
  other.merge(self)
end

#+(other) ⇒ Object

Operator for #merge.

CREDIT: Trans


57
58
59
# File 'lib/core/facets/hash/op.rb', line 57

def +(other)
  merge(other)
end

#-(other) ⇒ Object

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 mathcing keys are removed.

CREDIT: Trans


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/core/facets/hash/op.rb', line 67

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) ⇒ Object

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

CREDIT: Trans


8
9
10
11
12
13
14
# File 'lib/core/facets/hash/op.rb', line 8

def <<(other)
  if other.respond_to?(:to_ary)
    self.store(*other)
  else
    update(other)
  end
end

#alias!(newkey, oldkey) ⇒ Object

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


59
60
61
62
# File 'lib/core/facets/hash/rekey.rb', line 59

def alias!( newkey, oldkey )
  self[newkey] = self[oldkey] if self.has_key?(oldkey)
  self
end

#argumentize(args_field = nil) ⇒ Object

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


332
333
334
335
336
337
338
339
340
341
# File 'lib/more/facets/command.rb', line 332

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

#delete_unlessObject

Inverse of #delete_if.

CREDIT: Daniel Schierbeck


11
12
13
# File 'lib/core/facets/hash/delete.rb', line 11

def delete_unless #:yield:
  delete_if{ |key, value| ! yield(key, value) }
end

#delete_values(*values) ⇒ Object

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


24
25
26
# 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) ⇒ Object

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


42
43
44
# File 'lib/core/facets/hash/delete.rb', line 42

def delete_values_at(*keys, &yld)
  keys.map{|key| delete(key, &yld) }
end

#diff(h2) ⇒ Object

Difference comparison of two hashes.

CREDIT: ?

TODO:

- Rewrite #diff to be more readable.
- Rename #diff to #difference or something else?


105
106
107
# File 'lib/core/facets/hash/op.rb', line 105

def diff(h2)
  dup.send(:delete_if){|k,v| h2[k] == v}.send(:merge,h2.dup.send(:delete_if){ |k,v| has_key?(k) })
end

#each_with_key(&yld) ⇒ Object Also known as: each_with_index

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

CREDIT: Trans


8
9
10
# File 'lib/core/facets/hash/iterate.rb', line 8

def each_with_key( &yld )
  each_pair{ |k,v| yld.call(v,k) }
end

#except(*less_keys) ⇒ Object

Returns a new hash less the given keys.



24
25
26
# File 'lib/core/facets/hash/slice.rb', line 24

def except(*less_keys)
  slice(*keys - less_keys)
end

#except!(*less_keys) ⇒ Object

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}


35
36
37
38
39
# File 'lib/core/facets/hash/slice.rb', line 35

def except!(*less_keys)
  removed = slice(*less_keys)
  replace(except(*less_keys))
  removed
end

#has_keys?(*check_keys) ⇒ Boolean

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

Returns:

  • (Boolean)


12
13
14
15
# File 'lib/core/facets/hash/has_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) ⇒ Boolean

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

Returns:

  • (Boolean)


26
27
28
29
# File 'lib/core/facets/hash/has_keys.rb', line 26

def has_only_keys?(*check_keys)
  unknown_keys = self.keys - check_keys
  return unknown_keys.empty?
end

#insert(name, value) ⇒ Object

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

TODO: Would #store? be a better name?

CREDIT: Trans


10
11
12
13
14
15
16
17
# File 'lib/core/facets/hash/insert.rb', line 10

def insert(name, value)
  if key?(name)
    false
  else
    store(name,value)
    true
  end
end

#inverseObject

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


15
16
17
18
19
20
21
22
23
24
25
# File 'lib/core/facets/hash/inverse.rb', line 15

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 = '') ⇒ Object

Like Array#join but specialized to Hash.

CREDIT: Mauricio Fernandez


142
143
144
145
146
# File 'lib/core/facets/conversion.rb', line 142

def join(pair_divider='', elem_divider='')
  s = []
  each_pair { |k,v| s << "#{k}#{pair_divider}#{v}" }
  s.join(elem_divider)
end

#mash!(&yld) ⇒ Object Also known as: graph!, collate!

In place version of #mash.

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


47
48
49
# File 'lib/core/facets/enumerable/mash.rb', line 47

def mash!(&yld)
  replace(mash(&yld))
end

#normalize_keys(&block) ⇒ Object

Converts all keys in the Hash accroding to the given block. If the block return nil for given key, then that key will be left intact.

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

CREDIT: Trans
CREDIT: Gavin Sinclair


18
19
20
# File 'lib/core/facets/hash/keyize.rb', line 18

def normalize_keys( &block )
  dup.send(:normalize_keys!, &block)
end

#normalize_keys!(&block) ⇒ Object

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

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

CREDIT: Trans
CREDIT: Gavin Sinclair


31
32
33
34
35
36
37
# File 'lib/core/facets/hash/keyize.rb', line 31

def normalize_keys!( &block )
  keys.each{ |k|
    nk = block[k]
    self[nk]=delete(k) if nk
  }
  self
end

#pairs_at(*keys) ⇒ Object

Return a new hash with the specified entries.

{:a=>1,:b=>2}.pairs_at(:a,:c)  #=> {:a=>1, :c=>nil}

The later form is equivalent to #pairs_at.

CREDIT: Trans


24
25
26
# File 'lib/core/facets/hash/iterate.rb', line 24

def pairs_at( *keys )
  keys.inject({}) {|h,k| h[k] = self[k]; h}
end

#rand_keyObject

Returns a random key.

{:one => 1, :two => 2, :three => 3}.pick_key  #=> :three


175
176
177
# File 'lib/more/facets/random.rb', line 175

def rand_key
  keys.at( rand(keys.size) )
end

#rand_key!Object Also known as: pick_key

Delete a random key-value pair, returning the key.

a = {:one => 1, :two => 2, :three => 3}
a.pick_key!  #=> :two
a            #=> {:one => 1, :three => 3}


185
186
187
188
189
# File 'lib/more/facets/random.rb', line 185

def rand_key!
  k,v = rand_pair
  delete( k )
  return k
end

#rand_pairObject

Returns a random key-value pair.

{:one => 1, :two => 2, :three => 3}.pick  #=> [:one, 1]


197
198
199
200
# File 'lib/more/facets/random.rb', line 197

def rand_pair
  k = rand_key
  return k, fetch(k)
end

#rand_pair!Object Also known as: pick_pair

Deletes a random key-value pair and returns that pair.

a = {:one => 1, :two => 2, :three => 3}
a.rand_pair!  #=> [:two, 2]
a             #=> {:one => 1, :three => 3}


208
209
210
211
212
# File 'lib/more/facets/random.rb', line 208

def rand_pair!
  k,v = rand_pair
  delete( k )
  return k,v
end

#rand_valueObject Also known as: at_rand

Returns a random hash value.

{:one => 1, :two => 2, :three => 3}.rand_value  #=> 2
{:one => 1, :two => 2, :three => 3}.rand_value  #=> 1


221
222
223
# File 'lib/more/facets/random.rb', line 221

def rand_value
  fetch( rand_key )
end

#rand_value!Object Also known as: pick, at_rand!

Deletes a random key-value pair and returns the value.

a = {:one => 1, :two => 2, :three => 3}
a.at_rand!  #=> 2
a           #=> {:one => 1, :three => 3}


231
232
233
234
235
# File 'lib/more/facets/random.rb', line 231

def rand_value!
  k,v = rand_pair
  delete( k )
  return v
end

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

Converts all keys in the Hash accroding to the given block. If the block return 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

Raises:

  • (ArgumentError)


15
16
17
18
# File 'lib/core/facets/hash/rekey.rb', line 15

def rekey( meth=nil, &block )
  raise ArgumentError, "2 for 1" if meth and block
  dup.send(:rekey!, meth, &block)
end

#rekey!(meth = nil, &block) ⇒ Object

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

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
37
# File 'lib/core/facets/hash/rekey.rb', line 28

def rekey!( meth=nil, &block )
  meth = :to_sym unless meth or block
  raise ArgumentError, "2 for 1" if meth and block
  block = meth.to_sym.to_proc if meth
  keys.each do |k|
    nk = block[k]
    self[nk]=delete(k) if nk
  end
  self
end

#replace_eachObject

Same as #update_each, but deletes the key element first.

CREDIT: Trans


7
8
9
10
11
12
13
# File 'lib/core/facets/hash/update.rb', line 7

def replace_each  # :yield:
  dup.each do |k,v|
    delete(k)
    update(yield(k,v))
  end
  self
end

#restore_snapshot(snap) ⇒ Object



169
# File 'lib/more/facets/snapshot.rb', line 169

def restore_snapshot(snap) replace(snap) end

#reverse_merge(other) ⇒ Object

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.



15
16
17
# File 'lib/core/facets/hash/merge.rb', line 15

def reverse_merge(other)
  other.merge(self)
end

#reverse_merge!(other) ⇒ Object Also known as: reverse_update

Inplace form of #reverse_merge.



21
22
23
# File 'lib/core/facets/hash/merge.rb', line 21

def reverse_merge!(other)
  replace(reverse_merge(other))
end

#select!Object

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

CREDIT Gavin Sinclair
CREDIT Noah Gibbs


9
10
11
# File 'lib/core/facets/hash/select.rb', line 9

def select!
  reject! { |k,v| not yield(k,v) }
end

#shuffleObject

Returns a copy of the hash with values arranged in new random order.

h = {:a=>1, :b=>2, :c=>3}
h.shuffle_hash  #=> {:b=>2, :c=>1, :a>3}


248
249
250
# File 'lib/more/facets/random.rb', line 248

def shuffle
  Hash.zipnew( keys.sort_by{Kernel.rand}, values.sort_by{Kernel.rand} )
end

#shuffle!Object

Destructive shuffle_hash. Arrange the values in a new random order.

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


259
260
261
# File 'lib/more/facets/random.rb', line 259

def shuffle!
  self.replace( shuffle )
end

#slice(*keep_keys) ⇒ Object

Returns a new hash with only the given keys.



5
6
7
8
9
10
11
# File 'lib/core/facets/hash/slice.rb', line 5

def slice(*keep_keys)
  h = {}
  keep_keys.each do |key|
    h[key] = fetch(key)
  end
  h
end

#slice!(*keep_keys) ⇒ Object

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



16
17
18
19
20
# File 'lib/core/facets/hash/slice.rb', line 16

def slice!(*keep_keys)
  removed = except(*keep_keys)
  replace(slice(*keep_keys))
  removed
end

#stringify_keys(&filter) ⇒ Object Also known as: keys_to_s

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 }

CREDIT: Trans
CREDIT: Gavin Sinclair


49
50
51
52
53
54
55
# File 'lib/core/facets/hash/keyize.rb', line 49

def stringify_keys( &filter )
  if filter
    normalize_keys{ |k| filter[k] ? k.to_s : nil }
  else
    normalize_keys{ |k| k.to_s }
  end
end

#stringify_keys!(&filter) ⇒ Object Also known as: keys_to_s!

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 }

CREDIT: Trans
CREDIT: Gavin Sinclair


69
70
71
72
73
74
75
# File 'lib/core/facets/hash/keyize.rb', line 69

def stringify_keys!( &filter )
  if filter
    normalize_keys!{ |k| filter[k] ? k.to_s : nil }
  else
    normalize_keys!{ |k| k.to_s }
  end
end

#swap!(key1, key2) ⇒ Object

Swap the values of a pair of keys in place.

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

CREDIT: Gavin Sinclair


70
71
72
73
74
75
# File 'lib/core/facets/hash/rekey.rb', line 70

def swap!( key1, key2 )
  tmp = self[key1]
  self[key1] = self[key2]
  self[key2] = tmp
  self
end

#swapkey!(newkey, oldkey) ⇒ Object

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

Returns a reference to the Hash.

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

CREDIT: Gavin Sinclair


90
91
92
93
# File 'lib/core/facets/hash/rekey.rb', line 90

def swapkey!( newkey, oldkey )
  self[newkey] = self.delete(oldkey) if self.has_key?(oldkey)
  self
end

#symbolize_keys(&filter) ⇒ Object Also known as: keys_to_sym

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 }

CREDIT: Trans
CREDIT: Gavin Sinclair


89
90
91
92
93
94
95
# File 'lib/core/facets/hash/keyize.rb', line 89

def symbolize_keys( &filter )
  if filter
    normalize_keys{ |k| filter[k] ? k.to_sym : nil }
  else
    normalize_keys{ |k| k.to_sym }
  end
end

#symbolize_keys!(&filter) ⇒ Object Also known as: keys_to_sym!

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 }

CREDIT: Trans
CREDIT: Gavin Sinclair


115
116
117
118
119
120
121
122
# File 'lib/core/facets/hash/keyize.rb', line 115

def symbolize_keys!( &filter )
  if filter
    normalize_keys!{ |k| filter[k] ? k.to_sym : nil }
  else
    normalize_keys!{ |k| k.to_sym }
  end

end

#take_snapshotObject



168
# File 'lib/more/facets/snapshot.rb', line 168

def take_snapshot() dup end

#to_consoleObject

Convert an array into command line parameters. The array is accepted in the format of Ruby method arguments –ie. [arg1, arg2, …, hash]



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/more/facets/command.rb', line 309

def to_console
  flags = collect do |f,v|
    m = f.to_s.size == 1 ? '-' : '--'
    case v
    when Array
      v.collect{ |e| "#{m}#{f}='#{e}'" }.join(' ')
    when true
      "#{m}#{f}"
    when false, nil
      ''
    else
      "#{m}#{f}='#{v}'"
    end
  end
  flags.join(" ")
end

#to_hObject

Return a rehashing of self.

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

CREDIT: Forian Gross


154
# File 'lib/core/facets/conversion.rb', line 154

def to_h; rehash; end

#to_openobjectObject

Convert a Hash into an OpenObject.



215
216
217
# File 'lib/more/facets/openobject.rb', line 215

def to_openobject
  OpenObject[self]
end

#to_ostructObject

Turns a hash into a generic object using an OpenStruct.

o = { 'a' => 1 }.to_ostruct
o.a  #=> 1


187
188
189
# File 'lib/more/facets/ostruct.rb', line 187

def to_ostruct
  OpenStruct.new(self)
end

#to_ostruct_recurse(exclude = {}) ⇒ Object

Like to_ostruct but recusively objectifies all hash elements as well.

o = { 'a' => { 'b' => 1 } }.to_ostruct_recurse
o.a.b  #=> 1

The exclude parameter is used internally to prevent infinite recursion and is not intended to be utilized by the end-user. But for more advance use, if there is a particular subhash you would like to prevent from being converted to an OpoenStruct then include it in the exclude hash referencing itself. Eg.

h = { 'a' => { 'b' => 1 } }
o = h.to_ostruct_recurse( { h['a'] => h['a'] } )
o.a['b']  #=> 1


215
216
217
218
219
220
221
222
223
# File 'lib/more/facets/ostruct.rb', line 215

def to_ostruct_recurse(exclude={})
  return exclude[self] if exclude.key?( self )
  o = exclude[self] = OpenStruct.new
  h = self.dup
  each_pair do |k,v|
    h[k] = v.to_ostruct_recurse( exclude ) if v.respond_to?(:to_ostruct_recurse)
  end
  o.__update__(h)
end

#to_procObject

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


168
169
170
171
172
173
174
175
# File 'lib/core/facets/conversion.rb', line 168

def to_proc
  lambda do |o|
    self.each do |k,v|
      ke = "#{k}="
      o.__send__(ke, v)
    end
  end
end

#to_proc_with_reponseObject

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


184
185
186
187
188
189
190
191
# File 'lib/core/facets/conversion.rb', line 184

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) ⇒ Object

A method to convert a Hash into a Struct.

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

CREDIT: Daniel Berger


200
201
202
# File 'lib/core/facets/conversion.rb', line 200

def to_struct(struct_name)
  Struct.new(struct_name,*keys).new(*values)
end

#traverse(&b) ⇒ Object

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

CREDIT: Trans

– 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 (?)

++



19
20
21
22
23
24
25
26
# File 'lib/core/facets/hash/traverse.rb', line 19

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) ⇒ Object

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


37
38
39
# File 'lib/core/facets/hash/traverse.rb', line 37

def traverse!(&b)
  self.replace( self.traverse(&b) )
end

#update_eachObject

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


22
23
24
25
26
27
# File 'lib/core/facets/hash/update.rb', line 22

def update_each  # :yield:
  dup.each do |k,v|
   update(yield(k,v))
  end
  self
end

#update_keysObject

Iterate over hash updating kust the keys.

 h = {:a=>1, :b=>2}
 h.update_keys{ |k,v| "#{k}#{v}" }
 h  #=> { "a1"=>2, "b2"=>3 }

CREDIT: Trans


37
38
39
# File 'lib/core/facets/hash/update.rb', line 37

def update_keys #:yield:
  each{ |k,v| delete(k) ; store(yield(k), v) }
end

#update_valuesObject

Iterate over hash updating just the values.

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

CREDIT: Trans


49
50
51
# File 'lib/core/facets/hash/update.rb', line 49

def update_values #:yield:
  each{ |k,v| store(k, yield(v)) }
end

#variablize_keys(of_class = nil) ⇒ Object



144
145
146
# File 'lib/core/facets/hash/keyize.rb', line 144

def variablize_keys( of_class=nil )
  self.dup.variablize_keys!( of_class )
end

#variablize_keys!(of_class = nil) ⇒ Object

Synonym for Hash#keys_to_string, but modifies the receiver in place (and returns it). With a from_class parameter, limits conversion to only a certain class of keys. It defaults to nil which convert any key class.

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

CREDIT: Trans
CREDIT: David Hansson

Raises:

  • (ArgumentError)


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/core/facets/hash/keyize.rb', line 159

def variablize_keys!( of_class=nil )
  raise ArgumentError, "Parameter must be a class" unless of_class.kind_of?(Class) if of_class
  if of_class
    self.each_key do |k|
      if k.respond_to?(:to_s) and k.class == of_class
        k = k.to_s
        nk = k[0,1] != '@' ? k : "@#{k}"
        self[nk]=self.delete(k)
      end
    end
  else
    self.each_key do |k|
      if k.respond_to?(:to_s)
        k = k.to_s
        nk = k[0,1] != '@' ? k : "@#{k}"
        self[nk]=self.delete(k)
      end
    end
  end
  self
end

#weave(h) ⇒ Object

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

Raises:

  • (ArgumentError)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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) ⇒ Object

Operator for #reverse_merge.

CREDIT: Trans


49
50
51
# File 'lib/core/facets/hash/op.rb', line 49

def |(other)
  other.merge(self)
end