HashExtend
Extend ruby Hash. No override.
Installation
Add this line to your application's Gemfile:
gem 'hash_extend'
And then execute:
$ bundle
Or install it yourself as:
$ gem install hash_extend
Usage
stealth_delete
Delete key(s) passed by, but return the hash instead of the deleted value
stealth_delete! *keys
stealth_delete *keys
Demo
{:one=>1, :two=>2, :three=>3}.stealth_delete :one
#=> {:two=>2, :three=>3}
{:one=>1, :two=>2, :three=>3}.stealth_delete :one, :three
#=> {:two=>2}
{:one=>1, :two=>2, :three=>3}.stealth_delete :four
#=> {:one=>1, :two=>2, :three=>3}
{:one=>1, :two=>2, :three=>3}.stealth_delete :one, :four
#=> {:two=>2, :three=>3}
Code
def stealth_delete! *keys
keys.each do |key|
delete key
end
return self
end
map_values
Update values through block
map_values!
map_values
Demo
# square values
{:one=>1, :two=>2, :three=>3}.map_values{ |value| value ** 2 }
#=> {:one=>1, :two=>4, :three=>9}
Code
def map_values!
self.each do |key, value|
self[key] = yield value
end
end
map_keys
Update keys through block
map_keys!
map_keys
Demo
{"one"=>1, "two"=>2, "three"=>3}.map_keys(&:to_sym)
#=> {:one=>1, :two=>2, :three=>3}
Code
def map_keys
self.inject({}) do |hash, (key, value)|
hash[yield key] = value; hash
end
end
def map_keys! &block
to_map = self.dup
self.clear.merge! to_map.map_keys &block
end
Perfomances : Generaly, use the "!" is faster than the "no self modification" methods. Cause the last one used to "dup" the object. As we can't modify keys hash during iteration, here it's the reverse.
delete_many
Delete severals keys in one
Demo
h = Hash[:one, 1, :two, 2, :three, 3] #=> {:one=>1, :two=>2, :three=>3}
h.delete_many(:one, :three) #=> [1, 3]
h #=> {:two=>2}
h.delete_many(:six) #=> [nil]
Code
def delete_many *keys
keys.map{ |key| self.delete(key) }
end
insert
Insert a value through descendance of keys (hash in hash)
Demo
h = Hash.new #=> {}
h.insert(12, :calendar, :gregorian, :months)
#=> {:calendar => {:gregorian => {:months => 12}}}
h.insert(13, :calendar, :lunar, :months)
#=> {:calendar => {:gregorian => {:months => 12}, :lunar => {:months => 13}}}
Code
def insert value, *keys
if keys.size > 1
shifted = keys.shift
self[shifted] ||= Hash.new
self[shifted] = self[shifted].insert value, *keys
else
self[keys.first] = value
end
self
end
compact
Allow to compact hash just like arrays. Well, you can check nil, or black, or whatever you want on keys OR values
compact! = Hash.new
compact = Hash.new
Arguments : ':compare' must be in %wvalue, default is :value Arguments : ':with' is recommended in %wempty?, default is :nil?
Demo
{:one=>1, :two=>2, :three=>3, :four=>nil, :five=>[]}.compact!
#=> {:five=>[], :one=>1, :two=>2, :three=>3}
{:one=>1, :two=>2, :three=>3, :four=>nil, :five=>[]}.compact!(:with=>:blank?)
#=> {:one=>1, :two=>2, :three=>3}
# for the perverts ones
{:one=>1, :two=>2, :three=>3, :four=>nil, :five=>[]}.compact!(:with=>"is_a?(Fixnum)")
#=> {:four=>nil, :five=>[]}
# And for the ones who REALLY care about memory
{:one=>1, "two"=>2, "three"=>3, "four"=>nil, :five=>[]}.compact!(:compare => :key, :with=>"is_a?(String)")
#=> {:one=>1, :five=>[]}
Code
def compact! = Hash.new
compare = .delete(:compare) || :value
raise ArgumentError, ":compare option must be in %w{key value}" unless [:key, :value].include? compare.to_sym
if (with = .delete :with)
self.each do |key, value|
self.delete(key) if eval "#{ compare }.#{ with }"
end
else
self.each do |key, value|
self.delete(key) if eval "#{ compare }.nil?"
end
end
self
end
select_by
Select into hash from a collection of keys. Usefull to select correct params after a form.
select_by! *collection
select_by *collection
Demo
{:one=>1, :two=>2, :three=>3, :four=>4}.select_by :one, :three
#=> {:one=>1, :three=>3}
{:one=>1, :two=>2, :three=>3, :four=>4}.select_by :one, :six
#=> {:one=>1}
{:one=>1, :two=>2, :three=>3, :four=>4}.select_by :six, :seven
#=> {}
Code
def select_by! *collection
self.keep_if{ |field, _| collection.include? field.to_sym }
end
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request