- []
- []=
- alias!
- assert_has_keys
- assert_has_only_keys
- at_rand
- at_rand!
- collate
- collate!
- delete_unless
- each
- each_with_index
- each_with_key
- graph!
- has_keys?
- has_only_keys?
- inverse
- join
- keys_to_s
- keys_to_s!
- keys_to_sym
- keys_to_sym!
- pick
- pick_key
- pick_pair
- rand_key
- rand_key!
- rand_pair
- rand_pair!
- rand_value
- rand_value!
- replace_each
- shuffle
- shuffle!
- stringify_keys
- stringify_keys!
- swap!
- swapkey!
- symbolize_keys
- symbolize_keys!
- to_h
- to_ostruct
- to_ostruct_recurse
- to_proc
- to_proc_with_reponse
- traverse
- traverse!
- update_each
- update_keys
- update_values
- variablize_keys
- variablize_keys!
- weave
- zipnew
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 }
[ show source ]
# File lib/facets/core/hash/self/zipnew.rb, line 9 def self.zipnew(keys,values) # or some better name h = {} keys.size.times{ |i| h[ keys[i] ] = values[i] } h end
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]
[ show source ]
# File lib/facets/core/hash/op_fetch.rb, line 13 def []( *sliceKeys ) if sliceKeys.length == 1 return at( sliceKeys[0] ) else return values_at( *sliceKeys ) end end
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}
[ show source ]
# File lib/facets/core/hash/op_fetch.rb, line 31 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
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.
[ show source ]
# File lib/facets/core/hash/alias.rb, line 23 def alias!( newkey, oldkey ) self[newkey] = self[oldkey] if self.has_key?(oldkey) self end
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
[ show source ]
# File lib/facets/core/hash/assert_has_keys.rb, line 12 def assert_has_keys(*check_keys) raise(ArgumentError, "does not have key(s)") unless has_keys?(*check_keys) end
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
[ show source ]
# File lib/facets/core/hash/assert_has_only_keys.rb, line 12 def assert_has_only_keys(*check_keys) raise(ArgumentError, "has unexpected key(s)") unless has_only_keys?(*check_keys) end
Alias for rand_value
Alias for rand_value!
Returns a new hash built by iterating through each key,value pair and updating the new hash.
[ show source ]
# File lib/facets/core/hash/collate.rb, line 12 def collate # :yield: newhash = {} each_pair{ |k,v| newhash.update( yield(k,v) ) } newhash end
In place version of collate.
[ show source ]
# File lib/facets/core/hash/collate.rb, line 19 def collate!(&yld) replace( collate(&yld) ) end
[ show source ]
# File lib/facets/core/hash/delete_unless.rb, line 3 def delete_unless (&block) delete_if { |key, value| not block.call(key, value) } end
A "smarter" hasheach 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.
[ show source ]
# File lib/facets/core/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
Alias for each_with_key
[ show source ]
# File lib/facets/core/hash/each_with_key.rb, line 4 def each_with_key( &yld ) each_pair{ |k,v| yld.call(v,k) } end
As with Enumerable#graph but acts in place.
[ show source ]
# File lib/facets/core/hash/graph.rb, line 5 def graph!( &blk ) self.replace( graph( &blk ) ) 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
[ show source ]
# File lib/facets/core/hash/has_keys.rb, line 10 def has_keys?(*check_keys) unknown_keys = check_keys - self.keys return unknown_keys.empty? end
Returns true if the hash contains only the given keys, otherwise false.
h = { :a => 1, :b => 2 } h.has_only_keys?( :a, :b ) #=> true h.has_only_keys?( :a ) #=> false
[ show source ]
# File lib/facets/core/hash/has_only_keys.rb, line 10 def has_only_keys?(*check_keys) unknown_keys = self.keys - check_keys return unknown_keys.empty? 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
[ show source ]
# File lib/facets/core/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
[ show source ]
# File lib/facets/core/hash/join.rb, line 4 def join( pair_divider='', elem_divider='' ) s = [] each_pair { |k,v| s << "#{k}#{pair_divider}#{v}" } s.join(elem_divider) end
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 }
[ show source ]
# File lib/facets/core/hash/keys_to_s.rb, line 15 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
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 }
[ show source ]
# File lib/facets/core/hash/keys_to_s.rb, line 34 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
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 }
[ show source ]
# File lib/facets/core/hash/keys_to_sym.rb, line 15 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
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 }
[ show source ]
# File lib/facets/core/hash/keys_to_sym.rb, line 40 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
Alias for rand_value!
Alias for rand_key!
Alias for rand_pair!
Returns a random key.
{:one => 1, :two => 2, :three => 3}.pick_key #=> :three
[ show source ]
# File lib/facets/core/hash/rand_key.rb, line 7 def rand_key keys.at( rand(keys.size) ) end
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}
[ show source ]
# File lib/facets/core/hash/rand_key.rb, line 17 def rand_key! k,v = rand_pair delete( k ) return k end
Returns a random key-value pair.
{:one => 1, :two => 2, :three => 3}.pick #=> [:one, 1]
[ show source ]
# File lib/facets/core/hash/rand_pair.rb, line 9 def rand_pair k = rand_key return k, fetch(k) end
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}
[ show source ]
# File lib/facets/core/hash/rand_pair.rb, line 20 def rand_pair! k,v = rand_pair delete( k ) return k,v end
Returns a random hash value.
{:one => 1, :two => 2, :three => 3}.rand_value #=> 2 {:one => 1, :two => 2, :three => 3}.rand_value #=> 1
[ show source ]
# File lib/facets/core/hash/rand_value.rb, line 16 def rand_value fetch( rand_key ) end
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}
[ show source ]
# File lib/facets/core/hash/rand_value.rb, line 26 def rand_value! k,v = rand_pair delete( k ) return v end
Same as update_each, but deletes the key element first.
[ show source ]
# File lib/facets/core/hash/replace_each.rb, line 4 def replace_each # :yield: dup.each_pair{ |k,v| delete( k ); update( yield(k,v) ); } self end
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}
[ show source ]
# File lib/facets/core/hash/shuffle.rb, line 11 def shuffle Hash.zipnew( keys.sort_by{Kernel.rand}, values.sort_by{Kernel.rand} ) end
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}
[ show source ]
# File lib/facets/core/hash/shuffle.rb, line 22 def shuffle! self.replace( shuffle ) end
Alias for keys_to_s
Alias for keys_to_s!
Swap the values of a pair of keys in place.
{:a=>1,:b=>2}.swap! #=> {:a=>2,:b=>1}
[ show source ]
# File lib/facets/core/hash/swap.rb, line 7 def swap!( key1, key2 ) tmp = self[key1] self[key1] = self[key2] self[key2] = tmp self end
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 }
[ show source ]
# File lib/facets/core/hash/swapkey.rb, line 16 def swapkey!( newkey, oldkey ) self[newkey] = self.delete(oldkey) if self.has_key?(oldkey) self end
Alias for keys_to_sym
Alias for keys_to_sym!
Return a rehashing of self.
{"a"=>1,"b"=>2}.to_h #=> {"b"=>2,"a"=>1}
[ show source ]
# File lib/facets/core/hash/to_h.rb, line 10 def to_h; rehash; end
Turns a hash into a generic object using an OpenStruct.
o = { 'a' => 1 }.to_ostruct o.a #=> 1
[ show source ]
# File lib/facets/core/hash/to_ostruct.rb, line 10 def to_ostruct OpenStruct.new( self ) end
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
[ show source ]
# File lib/facets/core/hash/to_ostruct_recurse.rb, line 26 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
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
[ show source ]
# File lib/facets/core/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
[ show source ]
# File lib/facets/core/hash/to_proc.rb, line 24 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
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" }
[ show source ]
# File lib/facets/core/hash/traverse.rb, line 16 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
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" }
[ show source ]
# File lib/facets/core/hash/traverse.rb, line 32 def traverse!(&b) self.replace( self.traverse(&b) ) end
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
[ show source ]
# File lib/facets/core/hash/update_each.rb, line 14 def update_each # :yield: dup.each_pair{ |k,v| update( yield(k,v) ); } self end
[ show source ]
# File lib/facets/core/hash/update_keys.rb, line 4 def update_keys each{ |k,v| delete(k) ; store( yield(k), v ) } end
[ show source ]
# File lib/facets/core/hash/update_values.rb, line 4 def update_values each{ |k,v| store( k, yield(v) ) } end
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.variablize_keys #=> { "@name"=>"Gavin", "@wife"=>:Lisa } foo.inspect #=> { :name =>"Gavin", :wife=>:Lisa }
[ show source ]
# File lib/facets/core/hash/variablize_keys.rb, line 11 def variablize_keys( of_class=nil ) self.dup.variablize_keys!( of_class ) end
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 }
[ show source ]
# File lib/facets/core/hash/variablize_keys.rb, line 23 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
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
[ show source ]
# File lib/facets/core/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