# File lib/aquarium/extensions/hash.rb, line 7 def and other_hash return {} if other_hash.nil? or other_hash.empty? keys2 = Set.new(self.keys).intersection(Set.new(other_hash.keys)) result = {} keys2.each do |key| value1 = self[key] value2 = other_hash[key] if block_given? result[key] = yield value1, value2 elsif value1 == value2 or value1.eql?(value2) result[key] = value1 elsif value1.class == value2.class && value1.respond_to?(:&) result[key] = (value1 & value2) end end result end
It appears that Hash#== uses Object#== (i.e., self.object_id == other.object_id) when comparing hash keys. (Array#== uses the overridden #== for the elements.)
# File lib/aquarium/extensions/hash.rb, line 89 def eql_when_keys_compared? other return true if self.object_id == other.object_id return false unless self.class == other.class keys1 = sort_keys(self.keys) keys2 = sort_keys(other.keys) return false unless keys1.eql?(keys2) (0...keys1.size).each do |index| # Handle odd cases where eql? and == behavior differently return false unless self[keys1[index]].eql?(other[keys2[index]]) || self[keys1[index]] == other[keys2[index]] end true end
# File lib/aquarium/extensions/hash.rb, line 102 def equivalent_key key i = keys.index(key) i.nil? ? nil : keys[i] end
# File lib/aquarium/extensions/hash.rb, line 59 def minus other_hash result = self.dup return result if other_hash.nil? or other_hash.empty? result.each do |key, value| if other_hash.include?(key) value1 = self[key] value2 = other_hash[key] if block_given? result[key] = yield value1, value2 elsif value2.nil? # do nothing elsif value1 == value2 or value1.eql?(value2) result.delete key elsif value1.class == value2.class && value1.respond_to?(:-) result[key] = (value1 - value2) else # Hash#merge behavior result.delete key end elsif block_given? # Since the block might change the value's type (e.g., [] => Set...) result[key] = yield result[key], nil end end result end
Union of self with a second hash, which returns a new hash. It’s different from Hash#merge in that it attempts to merge non-equivalent values for the same key, using a block, if given, or if they are of the same type and respond to #|, using #| to merge the two values. Otherwise, it behaves like Hash#merge.
# File lib/aquarium/extensions/hash.rb, line 32 def or other_hash return self if other_hash.nil? result = {} new_keys = self.keys | other_hash.keys new_keys.each do |key| value1 = self[key] value2 = other_hash[key] if block_given? result[key] = yield value1, value2 elsif value1.nil? and not value2.nil? result[key] = value2 elsif (not value1.nil?) and value2.nil? result[key] = value1 elsif value1 == value2 or value1.eql?(value2) result[key] = value1 elsif value1.class == value2.class && value1.respond_to?(:|) result[key] = (value1 | value2) else # Hash#merge behavior result[key] = value2 end end result end