-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path03_json_like_tree.rb
141 lines (114 loc) · 2.56 KB
/
03_json_like_tree.rb
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
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
class BaseNode
attr_reader :id
def to_s
@id
end
end
class NodeStr < BaseNode
def initialize(id)
raise "Id must be a string" unless id.is_a?(String)
@id = id
end
end
class NodeArr < BaseNode
attr_reader :children
def initialize(id, children)
raise "Id must be a string" unless id.is_a?(String)
raise "Children of NodeArr must be a Array" unless children.is_a?(Array)
@id = id
@children = children
end
end
class NodeObj < BaseNode
attr_reader :children
def initialize(id, children)
raise "Id must be a string" unless id.is_a?(String)
raise "Children of NodeObj must be a Hash" unless children.is_a?(Hash)
@id = id
@children = children
end
end
type_cat = NodeStr.new("cat")
name_tom = NodeStr.new("Tom")
tom = NodeObj.new("Tom(obj)", {"type" => type_cat, "name" => name_tom })
type_dog = NodeStr.new("dog")
name_rex = NodeStr.new("Rex")
rex = NodeObj.new("Rex(obj)", {"type" => type_dog, "name" => name_rex })
pets = NodeArr.new("pets", [tom, rex])
user_age = NodeStr.new("27")
user_name = NodeStr.new("Sergey")
user = NodeObj.new("user", {"name" => user_name, "age" => user_age } )
root = NodeObj.new("root", {"pets" => pets, "user" => user})
class ItemBase
attr_reader :node
def to_s
node.to_s
end
end
class ItemStr < ItemBase
def initialize(node)
raise "Node for ItemStr must be NodeStr" unless node.is_a?(NodeStr)
@node = node
end
def next
nil
end
end
class ItemArr < ItemBase
def initialize(node)
raise "Node for ItemArr must be NodeArr" unless node.is_a?(NodeArr)
@node = node
@iter = node.children.each
end
def next
Item.new(@iter.next)
rescue StopIteration
nil
end
end
class ItemObj < ItemBase
def initialize(node)
raise "Node for ItemObj must be NodeObj" unless node.is_a?(NodeObj)
@node = node
@iter = node.children.values.each
end
def next
Item.new(@iter.next)
rescue StopIteration
nil
end
end
module Item
def self.new(node)
case node
when NodeStr then ItemStr.new(node)
when NodeArr then ItemArr.new(node)
when NodeObj then ItemObj.new(node)
else raise("Unknown node: #{node}")
end
end
end
class Traversal
def initialize(root)
@current = Item.new(root)
@stack = []
end
def next
while @current && new_cur = @current.next do
@stack.push(@current)
@current = new_cur
end
result = @current
@current = @stack.pop
result
end
end
def process(node)
puts node
end
puts "Traversal\n"
iter = Traversal.new(root)
while item = iter.next do
process(item)
end
puts