Class: Dentaku::FlatHash

Inherits:
Object
  • Object
show all
Defined in:
lib/dentaku/flat_hash.rb

Class Method Summary collapse

Class Method Details

.expand(hash) ⇒ Object

Inverse of from_hash: re-nests a hash whose keys may contain dots.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/dentaku/flat_hash.rb', line 63

def self.expand(hash)
  result = {}
  hash.each do |k, v|
    key_str = k.to_s
    if key_str.include?('.')
      parts   = key_str.split('.', -1)
      last    = parts.length - 1
      current = result
      if k.is_a?(Symbol)
        i = 0
        while i < last
          current = (current[parts[i].to_sym] ||= {})
          i += 1
        end
        current[parts[last].to_sym] = v
      else
        i = 0
        while i < last
          current = (current[parts[i]] ||= {})
          i += 1
        end
        current[parts[last]] = v
      end
    else
      result[k] = v
    end
  end
  result
end

.flatten_key(segments) ⇒ Object



56
57
58
59
60
# File 'lib/dentaku/flat_hash.rb', line 56

def self.flatten_key(segments)
  return segments.first if segments.length == 1
  key = segments.join('.')
  segments.first.is_a?(Symbol) ? key.to_sym : key
end

.flatten_keys(hash) ⇒ Object



50
51
52
53
54
# File 'lib/dentaku/flat_hash.rb', line 50

def self.flatten_keys(hash)
  result = {}
  hash.each { |k, v| result[flatten_key(k)] = v }
  result
end

.from_hash(h) ⇒ Object

Flattens a nested hash so that each leaf becomes a top-level entry whose key is the dot-joined path of segments leading to it. Non-Hash values (including Arrays) are treated as leaves. Empty nested Hashes are dropped, matching the historical behavior of this method.

The flattened key preserves the type (Symbol vs String) of the outermost key in the path: if the top-level key is a Symbol the joined key is a Symbol, otherwise it stays a String.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/dentaku/flat_hash.rb', line 11

def self.from_hash(h)
  return { "" => h } unless h.is_a?(Hash)

  acc = {}
  h.each do |k, v|
    if v.is_a?(Hash)
      unless v.empty?
        if k.is_a?(Symbol)
          flatten_leaves_sym(v, k.to_s, acc)
        else
          flatten_leaves_str(v, k.to_s, acc)
        end
      end
    else
      acc[k] = v
    end
  end
  acc
end

.from_hash_with_intermediates(h) ⇒ Object

Like from_hash, but additionally retains every intermediate nested Hash under its dot-joined path key.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/dentaku/flat_hash.rb', line 33

def self.from_hash_with_intermediates(h)
  return { "" => h } unless h.is_a?(Hash)

  acc = {}
  h.each do |k, v|
    acc[k] = v
    if v.is_a?(Hash) && !v.empty?
      if k.is_a?(Symbol)
        flatten_with_intermediates_sym(v, k.to_s, acc)
      else
        flatten_with_intermediates_str(v, k.to_s, acc)
      end
    end
  end
  acc
end

.write_pair_with_intermediates!(identifier, value, target) ⇒ Object

Writes the flattened “intermediates” form of ‘=> value` directly into `target`, without allocating an intermediate Hash. Used by the iterator AST nodes (map/filter/reduce/all/any/enum) where the result of `from_hash_with_intermediates` is otherwise immediately discarded after being merged into the per-iteration context.

Returns nothing meaningful; mutates ‘target`.



100
101
102
103
104
105
106
107
108
109
# File 'lib/dentaku/flat_hash.rb', line 100

def self.write_pair_with_intermediates!(identifier, value, target)
  target[identifier] = value
  return unless value.is_a?(Hash) && !value.empty?

  if identifier.is_a?(Symbol)
    flatten_with_intermediates_sym(value, identifier.to_s, target)
  else
    flatten_with_intermediates_str(value, identifier.to_s, target)
  end
end