Class: Hash
- Defined in:
- lib/nano/hash/inverse.rb,
lib/nano/hash/at.rb,
lib/nano/hash/each.rb,
lib/nano/hash/join.rb,
lib/nano/hash/to_h.rb,
lib/nano/hash/slice.rb,
lib/nano/hash/weave.rb,
lib/nano/hash/%3C%3C.rb,
lib/nano/hash/%5B%5D.rb,
lib/nano/hash/collate.rb,
lib/nano/hash/shuffle.rb,
lib/nano/hash/swap%21.rb,
lib/nano/hash/alias%21.rb,
lib/nano/hash/graph%21.rb,
lib/nano/hash/rand_key.rb,
lib/nano/hash/traverse.rb,
lib/nano/hash/%5B%5D%3D.rb,
lib/nano/hash/keys_to_s.rb,
lib/nano/hash/rand_pair.rb,
lib/nano/hash/collate%21.rb,
lib/nano/hash/rand_value.rb,
lib/nano/hash/shuffle%21.rb,
lib/nano/hash/swapkey%21.rb,
lib/nano/hash/to_ostruct.rb,
lib/nano/hash/has_keys%3F.rb,
lib/nano/hash/keys_to_sym.rb,
lib/nano/hash/traverse%21.rb,
lib/nano/hash/update_each.rb,
lib/nano/hash/%3A%3Azipnew.rb,
lib/nano/hash/keys_to_s%21.rb,
lib/nano/hash/replace_each.rb,
lib/nano/hash/delete_unless.rb,
lib/nano/hash/keys_to_sym%21.rb,
lib/nano/hash/assert_has_keys.rb,
lib/nano/hash/has_only_keys%3F.rb,
lib/nano/hash/to_ostruct_recurse.rb,
lib/nano/hash/assert_has_only_keys.rb
Overview
Daniel Schierbeck
Class Method Summary collapse
-
.zipnew(keys, values) ⇒ Object
Creates a new hash from two arrays –a keys array and a values array.
Instance Method Summary collapse
-
#[](*sliceKeys) ⇒ Object
Adds slicing to Hash#[].
-
#[]=(*args) ⇒ Object
Add slicing to element assignment operator.
-
#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.
-
#assert_has_keys(*check_keys) ⇒ Object
Returns true is hash has the given keys, otherwise throws an ArgumentError.
-
#assert_has_only_keys(*check_keys) ⇒ Object
Returns true is hash has only then given keys, otherwise throws an ArgumentError.
- #at ⇒ Object
-
#collate ⇒ Object
Returns a new hash built by iterating through each key,value pair and updating the new hash.
-
#collate!(&yld) ⇒ Object
In place version of #collate.
- #delete_unless(&block) ⇒ Object
-
#each(&yld) ⇒ Object
A “smarter” hash#each which iterates through each value if only one block parameter is given.
-
#graph!(&blk) ⇒ Object
As with Enumerable#graph but acts in place.
-
#has_keys?(*check_keys) ⇒ Boolean
Returns true or false whether the hash contains the given keys.
-
#has_only_keys?(*check_keys) ⇒ Boolean
Returns true if the hash contains only the given keys, otherwise false.
-
#inverse ⇒ Object
Create a “true” inverse hash by storing mutliple values in Arrays.
- #join(pair_divider = '', elem_divider = '') ⇒ Object
-
#keys_to_s(from_class = nil) ⇒ Object
(also: #stringify_keys)
Converts all keys in the Hash to be String values, returning a new Hash.
-
#keys_to_s!(from_class = nil) ⇒ Object
(also: #stringify_keys!)
Synonym for Hash#keys_to_string, but modifies the receiver in place (and returns it).
-
#keys_to_sym(from_class = String) ⇒ Object
(also: #symbolize_keys)
Converts all keys in the Hash to be Symbol values, returning a new Hash.
-
#keys_to_sym!(from_class = String) ⇒ Object
(also: #symbolize_keys!)
Synonym for Hash#keys_to_symbol, but modifies the receiver in place (and returns it).
-
#rand_key ⇒ Object
Returns a random key.
-
#rand_key! ⇒ Object
(also: #pick_key)
Delete a random key-value pair, returning the key.
-
#rand_pair ⇒ Object
Returns a random key-value pair.
-
#rand_pair! ⇒ Object
(also: #pick_pair)
Deletes a random key-value pair and returns that pair.
-
#rand_value ⇒ Object
(also: #at_rand)
Returns a random hash value.
-
#rand_value! ⇒ Object
(also: #pick, #at_rand!)
Deletes a random key-value pair and returns the value.
-
#replace_each ⇒ Object
Same as #update_each, but deletes the key element first.
-
#shuffle ⇒ Object
Returns a copy of the hash with values arranged in new random order.
-
#shuffle! ⇒ Object
Destructive shuffle_hash.
-
#swap!(key1, key2) ⇒ Object
Swap the values of a pair of keys in place.
-
#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.
-
#to_h ⇒ Object
Return a rehashing of self.
-
#to_ostruct ⇒ Object
Turns a hash into a generic object using an OpenStruct.
-
#to_ostruct_recurse ⇒ Object
Like to_ostruct but recusively objectifies all hash elements as well.
-
#traverse(&b) ⇒ Object
Returns a new hash created by traversing the hash and its subhashes, executing the given block on the key and value.
-
#traverse!(&yld) ⇒ Object
In place version of traverse, which traverses the hash and its subhashes, executing the given block on the key and value.
-
#update_each ⇒ Object
Iterates through each pair and updates a the hash in place.
-
#weave(h) ⇒ Object
Weaves two hashes producing a new hash.
Class Method Details
.zipnew(keys, values) ⇒ Object
Creates a new hash from two arrays –a keys array and a values array.
Hah.zipnew(["a","b","c"], [1,2,3])
#=> { "a"=>1, "b"=>2, "c"=>3 }
9 10 11 12 13 |
# File 'lib/nano/hash/%3A%3Azipnew.rb', line 9 def self.zipnew(keys,values) # or some better name h = {} keys.size.times{ |i| h[ keys[i] ] = values[i] } h end |
Instance Method Details
#[](*sliceKeys) ⇒ Object
Adds slicing to Hash#[]. If more than one key arguments is given to Hash#[]
, the return value will be an array of the corresponding values.
h = { :a => 1, :b => 2, :c => 3 }
h[:a] #=> 1
h[:a, :b] #=> [1,2]
13 14 15 16 17 18 19 |
# File 'lib/nano/hash/%5B%5D.rb', line 13 def []( *sliceKeys ) if sliceKeys.length == 1 return at( sliceKeys[0] ) else return values_at( *sliceKeys ) end end |
#[]=(*args) ⇒ Object
Add slicing to element assignment operator.
h = {:a=>1, :b=>2, :c=>3}
h[:a] = 9 #=> 9
h #=> {:a=>9, :b=>2, :c=>3}
h[:a, :c] = [10,11] #=> [10,11]
h #=> {:a=>10, :b=>2, :c=>11}
14 15 16 17 18 19 20 21 |
# File 'lib/nano/hash/%5B%5D%3D.rb', line 14 def []=( *args ) if args.length <= 2 return store( *args ) end aVals = args.pop aVals = [aVals] unless aVals.kind_of?( Array ) args.each_index{ |i| store( args[i], aVals[i] ) } 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.
23 24 25 26 |
# File 'lib/nano/hash/alias%21.rb', line 23 def alias!( newkey, oldkey ) self[newkey] = self[oldkey] if self.has_key?(oldkey) self end |
#assert_has_keys(*check_keys) ⇒ Object
Returns true is hash has the given keys, otherwise throws an ArgumentError.
h = { :a => 1, :b => 2 }
h.assert_has_keys( :a ) #=> true
h.assert_has_keys( :c ) #=> ArgumentError
10 11 12 |
# File 'lib/nano/hash/assert_has_keys.rb', line 10 def assert_has_keys(*check_keys) raise(ArgumentError, "does not have key(s)") unless has_keys?(*check_keys) end |
#assert_has_only_keys(*check_keys) ⇒ Object
Returns true is hash has only then given keys, otherwise throws an ArgumentError.
h = { :a => 1, :b => 2 }
h.assert_has_only_keys( :a, :b ) #=> true
h.assert_has_only_keys( :a ) #=> ArgumentError
10 11 12 |
# File 'lib/nano/hash/assert_has_only_keys.rb', line 10 def assert_has_only_keys(*check_keys) raise(ArgumentError, "has unexpected key(s)") unless has_only_keys?(*check_keys) end |
#at ⇒ Object
2 |
# File 'lib/nano/hash/at.rb', line 2 alias_method( :at, :[] ) |
#collate ⇒ Object
Returns a new hash built by iterating through each key,value pair and updating the new hash.
– Note that this method may get some fine tuning as it currently expects the block to return a “mini-hash” pair – parhaps a 2-element array woud be better? ++
13 14 15 16 17 |
# File 'lib/nano/hash/collate.rb', line 13 def collate # :yield: newhash = {} each_pair{ |k,v| newhash.update( yield(k,v) ) } newhash end |
#collate!(&yld) ⇒ Object
In place version of #collate.
6 7 8 |
# File 'lib/nano/hash/collate%21.rb', line 6 def collate!(&yld) replace( collate(&yld) ) end |
#delete_unless(&block) ⇒ Object
3 4 5 |
# File 'lib/nano/hash/delete_unless.rb', line 3 def delete_unless (&block) delete_if { |key, value| not block.call(key, value) } end |
#each(&yld) ⇒ Object
A “smarter” hash#each which iterates through each value if only one block parameter is given.
{:a=>"a", 2=>"b", "x"=>"c"}.each{ |v| puts v }
produces
a
b
c
WARNING! Use with caution. Methods from other libraries may depend on the old behavior, expecting a two element array to be passed into a single block argument.
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nano/hash/each.rb', line 19 def each(&yld) case yld.arity when 0 when 1 each_value{|v| yield(v)} else each_pair{|k,v| yld.call(k,v)} end self end |
#graph!(&blk) ⇒ Object
As with Enumerable#graph but acts in place.
5 6 7 |
# File 'lib/nano/hash/graph%21.rb', line 5 def graph!( &blk ) self.replace( graph( &blk ) ) 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
10 11 12 13 |
# File 'lib/nano/hash/has_keys%3F.rb', line 10 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
10 11 12 13 |
# File 'lib/nano/hash/has_only_keys%3F.rb', line 10 def has_only_keys?(*check_keys) unknown_keys = self.keys - check_keys return unknown_keys.empty? end |
#inverse ⇒ Object
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
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/nano/hash/inverse.rb', line 16 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
2 3 4 5 6 |
# File 'lib/nano/hash/join.rb', line 2 def join( pair_divider='', elem_divider='' ) s = [] each_pair { |k,v| s << "#{k}#{pair_divider}#{v}" } s.join(elem_divider) end |
#keys_to_s(from_class = nil) ⇒ Object Also known as: stringify_keys
Converts all keys in the Hash to be String values, returning a new Hash. 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.keys_to_s #=> { "name"=>"Gavin", "wife"=>:Lisa }
foo.inspect #=> { :name =>"Gavin", :wife=>:Lisa }
– Adapted from Gavin Sinclair’s #convert_keys. ++
16 17 18 19 |
# File 'lib/nano/hash/keys_to_s.rb', line 16 def keys_to_s( from_class=nil ) raise ArgumentError, "Parameter must be a class" unless from_class.kind_of?(Class) if from_class self.dup.keys_to_s!( from_class ) end |
#keys_to_s!(from_class = nil) ⇒ Object Also known as: stringify_keys!
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.keys_to_s! #=> { "name"=>"Gavin", "wife"=>:Lisa }
foo.inspect #=> { "name"=>"Gavin", "wife"=>:Lisa }
– Adapted from Gavin Sinclair’s #convert_keys. ++
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nano/hash/keys_to_s%21.rb', line 16 def keys_to_s!( from_class=nil ) raise ArgumentError, "Parameter must be a class" unless from_class.kind_of?(Class) if from_class if from_class self.each_key{ |k| self[k.to_s]=self.delete(k) if k.respond_to?(:to_s) and k.class == from_class } else self.each_key{ |k| self[k.to_s]=self.delete(k) if k.respond_to?(:to_s) } end self end |
#keys_to_sym(from_class = String) ⇒ Object Also known as: symbolize_keys
Converts all keys in the Hash to be Symbol values, returning a new Hash. With a from_class parameter, limits conversion to only a certain class of keys. It defaults to String –use nil to convert any key class.
foo = { :name=>'Gavin', 'wife'=>:Lisa }
foo.keys_to_sym #=> { :name=>"Gavin", :wife=>:Lisa }
foo.inspect #=> { "name" =>"Gavin", "wife"=>:Lisa }
– Adapted from Gavin Sinclair’s graceous work #symbolify_keys. ++
16 17 18 19 |
# File 'lib/nano/hash/keys_to_sym.rb', line 16 def keys_to_sym( from_class=String ) raise ArgumentError, "Parameter must be a class" unless from_class.kind_of?(Class) if from_class self.dup.keys_to_sym!( from_class ) end |
#keys_to_sym!(from_class = String) ⇒ Object Also known as: symbolize_keys!
Synonym for Hash#keys_to_symbol, 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 String –use nil to convert any key class.
foo = { 'name'=>'Gavin', 'wife'=>:Lisa }
foo.keys_to_sym! #=> { :name=>"Gavin", :wife=>:Lisa }
foo.inspect #=> { :name=>"Gavin", :wife=>:Lisa }
– Adapted from Gavin Sinclair’s graceous work #symbolify_keys! ++
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/nano/hash/keys_to_sym%21.rb', line 16 def keys_to_sym!( from_class=String ) raise ArgumentError, "Parameter must be a class" unless from_class.kind_of?(Class) if from_class if from_class self.each_key{ |k| self[k.to_sym]=self.delete(k) if k.respond_to?(:to_sym) and k.class == from_class } else self.each_key{ |k| self[k.to_sym]=self.delete(k) if k.respond_to?(:to_sym) } end self end |
#rand_key ⇒ Object
Returns a random key.
{:one => 1, :two => 2, :three => 3}.pick_key #=> :three
7 8 9 |
# File 'lib/nano/hash/rand_key.rb', line 7 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}
17 18 19 20 21 |
# File 'lib/nano/hash/rand_key.rb', line 17 def rand_key! k,v = rand_pair delete( k ) return k end |
#rand_pair ⇒ Object
Returns a random key-value pair.
{:one => 1, :two => 2, :three => 3}.pick #=> [:one, 1]
7 8 9 10 |
# File 'lib/nano/hash/rand_pair.rb', line 7 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}
18 19 20 21 22 |
# File 'lib/nano/hash/rand_pair.rb', line 18 def rand_pair! k,v = rand_pair delete( k ) return k,v end |
#rand_value ⇒ Object 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
14 15 16 |
# File 'lib/nano/hash/rand_value.rb', line 14 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}
24 25 26 27 28 |
# File 'lib/nano/hash/rand_value.rb', line 24 def rand_value! k,v = rand_pair delete( k ) return v end |
#replace_each ⇒ Object
Same as #update_each, but deletes the key element first.
4 5 6 7 |
# File 'lib/nano/hash/replace_each.rb', line 4 def replace_each # :yield: dup.each_pair{ |k,v| delete( k ); update( yield(k,v) ); } self end |
#shuffle ⇒ Object
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}
11 12 13 |
# File 'lib/nano/hash/shuffle.rb', line 11 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}
12 13 14 |
# File 'lib/nano/hash/shuffle%21.rb', line 12 def shuffle! self.replace( shuffle ) end |
#swap!(key1, key2) ⇒ Object
Swap the values of a pair of keys in place.
{:a=>1,:b=>2}.swap! #=> {:a=>2,:b=>1}
7 8 9 10 11 12 |
# File 'lib/nano/hash/swap%21.rb', line 7 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 goes to Gavin Sinclair. ++
16 17 18 19 |
# File 'lib/nano/hash/swapkey%21.rb', line 16 def swapkey!( newkey, oldkey ) self[newkey] = self.delete(oldkey) if self.has_key?(oldkey) self end |
#to_h ⇒ Object
Return a rehashing of self.
{"a"=>1,"b"=>2}.to_h #=> {"b"=>2,"a"=>1}
– A horse is a horse, a horse of course. ++
10 |
# File 'lib/nano/hash/to_h.rb', line 10 def to_h; rehash; end |
#to_ostruct ⇒ Object
Turns a hash into a generic object using an OpenStruct.
o = { 'a' => 1 }.to_ostruct
o.a #=> 1
10 11 12 |
# File 'lib/nano/hash/to_ostruct.rb', line 10 def to_ostruct OpenStruct.new( self ) end |
#to_ostruct_recurse ⇒ Object
Like to_ostruct but recusively objectifies all hash elements as well.
o = { 'a' => { 'b' => 1 } }.to_ostruct_recurse
o.a.b #=> 1
11 12 13 14 15 16 17 |
# File 'lib/nano/hash/to_ostruct_recurse.rb', line 11 def to_ostruct_recurse o = self.dup each_pair do |k,v| o[k] = v.to_ostruct_recurse if v.respond_to?( :to_ostruct_recurse ) end OpenStruct.new( o ) 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" }
h.traverse { |k,v| [k.downcase, v] }
h #=> { "a"=>"A", "b"=>"B" }
13 14 15 16 17 18 19 |
# File 'lib/nano/hash/traverse.rb', line 13 def traverse(&b) inject({}) do |h,(k,v)| nk, nv = b[k,v] h[nk] = ( Hash === v ? v.traverse(&b) : nv ) h end end |
#traverse!(&yld) ⇒ 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" }
12 13 14 |
# File 'lib/nano/hash/traverse%21.rb', line 12 def traverse!( &yld ) self.replace( self.traverse( &yld ) ) end |
#update_each ⇒ Object
Iterates through each pair and updates a the hash in place. This is formally equivalent to #collate! But does not use #collate to accomplish the task. Hence #update_each is probably a bit faster.
# TODO
– Note that this may get some fine tuning as currently it expects the block to return a “mini-hash” pair. ++
14 15 16 17 |
# File 'lib/nano/hash/update_each.rb', line 14 def update_each # :yield: dup.each_pair{ |k,v| update( yield(k,v) ); } self end |
#weave(h) ⇒ Object
Weaves two hashes producing 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)
valueA, valueB => valueB
</tt>
Example:
# to do
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/nano/hash/weave.rb', line 23 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 |