Module: DR::CoreExt::Hash

Defined in:
lib/drain/ruby_ext/core_ext.rb

Instance Method Summary collapse

Instance Method Details

#deep_merge(other_hash, &block) ⇒ Object

Returns a new hash with +self+ and +other_hash+ merged recursively.

h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
h2 = { x: { y: [7,8,9] }, z: 'xyz' }

h1.deep_merge(h2) #=> {x: {y: [7, 8, 9]}, z: "xyz"}
h2.deep_merge(h1) #=> {x: {y: [4, 5, 6]}, z: [7, 8, 9]}
h1.deep_merge(h2) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
#=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}

Adapted from active support


33
34
35
# File 'lib/drain/ruby_ext/core_ext.rb', line 33

def deep_merge(other_hash, &block)
  dup.deep_merge!(other_hash, &block)
end

#deep_merge!(other_hash, &block) ⇒ Object

Same as +deep_merge+, but modifies +self+.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/drain/ruby_ext/core_ext.rb', line 38

def deep_merge!(other_hash, &block)
  return unless other_hash
  other_hash.each_pair do |k,v|
    tv = self[k]
    case
    when tv.is_a?(Hash) && v.is_a?(Hash)
      self[k] = tv.deep_merge(v, &block)
    when tv.is_a?(Array) && v.is_a?(Array)
      if v.length > 0 && v.first.nil? then
        #hack: if the array begins with nil, we append the new
        #value rather than overwrite it
        v.shift
        self[k] += v
      else
        self[k] = block && tv ? block.call(k, tv, v) : v
      end
    when tv.nil? && v.is_a?(Array)
      #here we still need to remove nil (see above)
      if v.length > 0 && v.first.nil? then
        v.shift
        self[k]=v
      else
        self[k] = block && tv ? block.call(k, tv, v) : v
      end
    else
      self[k] = block && tv ? block.call(k, tv, v) : v
    end
  end
  self
end

#inverseObject

from a hash [values] produce a hash [keys] there is already Hash#key which does that, but the difference here is that we flatten Enumerable values



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/drain/ruby_ext/core_ext.rb', line 72

def inverse
  r={}
  each_key do |k|
    values=fetch(k)
    values=[values] unless values.respond_to?(:each)
    values.each do |v|
      r[v]||=[]
      r[v]<< k
    end
  end
  return r
end

#keyed_value(key, sep: "/") ⇒ Object

take a key of the form ploum/plam/plim and return self[:ploum][:plam][:plim]



96
97
98
99
100
101
102
103
104
# File 'lib/drain/ruby_ext/core_ext.rb', line 96

def keyed_value(key, sep: "/")
  r=self.dup
  return r if key.empty?
  key.split(sep).each do |k|
    k=k.to_sym if r.key?(k.to_sym) && !r.key?(k)
    r=r[k]
  end
  return r
end

#sort_allObject

sort the keys and the values of the hash



86
87
88
89
90
91
92
# File 'lib/drain/ruby_ext/core_ext.rb', line 86

def sort_all
  r=::Hash[self.sort]
  r.each do |k,v|
    r[k]=v.sort
  end
  return r
end