Here are some potentiall useful one-liner methods for extracting and merging only parts of Hashes. I was surprised to find out that Hash didn’t already have built-in methods to do these things. Maybe they’re considered so obvious that they don’t need to be built-in, but I think the readability gain is worth it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
class Hash # Return a copy of the receiver with only the given keys. # # >> {:a => 1, :b => 2, :c => 3}.with_only(:a, :c) # => {:a => 1, :c => 3} # def with_only( *keys ) reject{ |k,v| not keys.include?(k) } end # Return a copy of the receiver without the given keys. # # >> {:a => 1, :b => 2, :c => 3}.without(:a, :c) # => {:b => 2} # def without( *keys ) reject{ |k,v| keys.include?(k) } end # Like #merge, but only accepts keys that the receiver already has. # # >> {:a => 1, :b => 2}.merge_existing({:a => 0, :c => 0}) # => {:a => 0, :b => 2} # def merge_existing( other ) merge( other.with_only(*self.keys) ) end # Like #merge_existing, but modifies the receiver. # def merge_existing!( other ) merge!( other.with_only(*self.keys) ) end alias :update_existing :merge_existing! end |
2 Comments
Hello Jacius!!!
Really good one liners.
But why don’t do with_only like this:
def with_only( *keys )
select{ |k,v| keys.include?(k) }
end
I guess reject + not is the same as select….
See ya
@Daniel: That was my first thought as well. But strangely, Hash#select doesn’t return a Hash, it returns nested arrays, like `[[:a, 1], [:b, 2]]`. So, using reject turned out to be the simplest way.