Module: Aquarium::Extensions::HashHelper

Included in:
Hash
Defined in:
lib/aquarium/extensions/hash.rb

Instance Method Summary collapse

Instance Method Details

#and(other_hash) ⇒ Object Also known as: intersection, &



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 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

#eql_when_keys_compared?(other) ⇒ Boolean

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.)

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
99
100
# 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

#equivalent_key(key) ⇒ Object



102
103
104
105
# File 'lib/aquarium/extensions/hash.rb', line 102

def equivalent_key key
  i = keys.index(key)
  i.nil? ? nil : keys[i] 
end

#minus(other_hash) ⇒ Object Also known as: -



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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

#or(other_hash) ⇒ Object Also known as: union, |

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.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 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