Сортировка по вложенному набору - PullRequest
0 голосов
/ 17 марта 2020
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

Я хочу отсортировать эту структуру вложенного набора в алфавитном порядке, сначала должны быть отсортированы родители, а затем дочерний элемент, а затем внуки.

Это уже реализовано в удивительном геме вложенного набора в рельсах. но это не дает мне внуков в отсортированном порядке, только родители в отсортированном порядке. Я также попытался использовать свойство order_column в разделе модели, но получил тот же результат - родители были отсортированы, но не внуки. Я также проверил упомянутый вопрос здесь и здесь , но он не помог. Как мы можем подойти к этой проблеме?

Редактировать: Итак, это массив объектов.

Ввод:

A
 - C
 - B

Output:

A
 - B
 - C

Проблема в том, что если у меня есть внуки, существующие реализации не сортируют его.

1 Ответ

0 голосов
/ 17 марта 2020

Не знаю, действительно ли вы ищете следующее, но если это не так, вы можете адаптировать его к вашим потребностям.

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) отображает каждый из этих двухэлементных массивов в последний элемент массива.

...