Не знаю, действительно ли вы ищете следующее, но если это не так, вы можете адаптировать его к вашим потребностям.
str =<<~END
Parent 1
|
|-Child 1
|- - Child 1_GrandChild1
|
|-Child 2
|
Parent 2
|
|-Child 1
|- - Child 1_GrandChild1
|- - Child 1_GrandChild2
|
|-Child 2
|
|-Child 3
|- - Child 3_GrandChild1
|
Parent 3
END
str.each_line.with_object([]) do |s,arr|
s.chomp!
case s
when /\A\p{Alpha}+\s+\d+\z/
arr << [0,s]
when /\A \|\-\p{Alpha}+\s+\d+\z/
arr << [1,s[/[A-Z].*/]]
when /\A \|\- \- \p{Alpha}+ \d+\_\p{Alpha}+\d+\z/
arr << [2,s[/\d.*/]]
end
end.sort.map(&:last)
#=> ["Parent 1", "Parent 2", "Parent 3", "Child 1", "Child 1", "Child 2",
# "Child 2", "Child 3", "1_GrandChild1", "1_GrandChild1", "1_GrandChild2",
# "3_GrandChild1"]
Обратите внимание, что
a = str.each_line.with_object([]) do |s,arr|
s.chomp!
case s
when /\A\p{Alpha}+\s+\d+\z/
arr << [0,s]
when /\A \|\-\p{Alpha}+\s+\d+\z/
arr << [1,s[/[A-Z].*/]]
when /\A \|\- \- \p{Alpha}+ \d+\_\p{Alpha}+\d+\z/
arr << [2,s[/\d.*/]]
end
end
#=> [[0, "Parent 1"], [1, "Child 1"], [2, "1_GrandChild1"],
# [1, "Child 2"], [0, "Parent 2"], [1, "Child 1"],
# [2, "1_GrandChild1"], [2, "1_GrandChild2"], [1, "Child 2"],
# [1, "Child 3"], [2, "3_GrandChild1"], [0, "Parent 3"]]
sort
, следовательно, сначала сортирует по первому элементу каждого двухэлементного массива, а затем сортирует по второму элементу, чтобы разорвать связи:
b = a.sort
#=> [[0, "Parent 1"], [0, "Parent 2"], [0, "Parent 3"],
# [1, "Child 1"], [1, "Child 1"], [1, "Child 2"], [1, "Child 2"],
# [1, "Child 3"],
# [2, "1_GrandChild1"], [2, "1_GrandChild1"], [2, "1_GrandChild2"],
# [2, "3_GrandChild1"]]
Наконец, b.map(&:last)
отображает каждый из этих двухэлементных массивов в последний элемент массива.