Created
July 18, 2016 10:24
-
-
Save ProGM/79e72876dbbcbbd79a2beec893c4f6e8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Tree | |
attr_reader :data | |
def initialize(data) | |
@data = data | |
end | |
def +(other) | |
Tree.new(deep_merge(@data, other.is_a?(Tree) ? other.data : other)) | |
end | |
delegate :empty?, to: :data | |
def replace(other) | |
@data.replace(other.data) | |
end | |
def root | |
level(0) | |
end | |
def levels | |
output = [] | |
i = -1 | |
while i += 1 | |
current_level = level(i) | |
break if current_level.all?(&:nil?) | |
output << current_level | |
end | |
output | |
end | |
def level(level_number) | |
all_elements_at_level(@data, level_number) | |
end | |
private | |
def deep_merge(a, b) | |
case a | |
when Hash | |
return merge_hashes(a, b) if b.is_a?(Hash) | |
return merge_array_hash(b, a) if b.is_a?(Array) | |
[b, a] | |
when Array | |
return merge_arrays(a, b) if b.is_a?(Array) | |
return merge_array_hash(a, b) if b.is_a?(Hash) | |
[b] + a | |
else | |
return [a, b] if b.is_a?(Hash) | |
return [a] + b if b.is_a?(Array) | |
a == b ? a : [a, b] | |
end | |
end | |
def merge_array_hash(a, b) | |
if a.last.is_a? Hash | |
a[0...-1] + [merge_hashes(a.last, b)] | |
else | |
a + [b] | |
end | |
end | |
def merge_hashes(a, b) | |
a.deep_merge(b) do |_, this_val, other_val| | |
deep_merge(this_val, other_val) | |
end | |
end | |
def merge_arrays(a, b) | |
keys = merge_array_keys(a, b) | |
hashes = merge_hashes(a.last.is_a?(Hash) ? a.last : {}, b.last.is_a?(Hash) ? b.last : {}) | |
if hashes.empty? | |
keys | |
else | |
(keys - hashes.keys) + [hashes] | |
end | |
end | |
def merge_array_keys(a, b) | |
(a.reject { |e| e.is_a?(Hash) } + b.reject { |e| e.is_a?(Hash) }).uniq | |
end | |
def all_elements_at_level(data, level_number) | |
return ground_level(data) if level_number == 0 | |
case data | |
when Hash | |
data.map { |_, v| all_elements_at_level(v, level_number - 1) } | |
when Array | |
data.map { |e| all_elements_at_level(e, level_number) }.flatten | |
end | |
end | |
def ground_level(data) | |
case data | |
when Hash | |
data.keys | |
when Array | |
data.map { |e| all_elements_at_level(e, 0) }.flatten | |
else | |
data | |
end | |
end | |
end |
@ProGM I would like to get the data as a tree looking like
{
"name" => data,
"children" => [{
"name" => data,
"children" => []
}]
}
I didn't arrive to make the change ... any idea ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You just save my day !! <3 Thank you !