ruby 嵌套集排序

bd1hkmkf  于 2023-08-04  发布在  Ruby
关注(0)|答案(2)|浏览(79)
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

字符串
我想按字母顺序对这个嵌套的集合结构进行排序,首先应该对父类进行排序,然后是子类,然后是孙类。
这已经在rails中的nested set gem中实现了,但是它没有按排序顺序给予孙代,只有父代是按排序顺序的。我还尝试在模型部分使用order_column属性,但得到了相同的结果--父代被排序,而孙代没有。我也检查了提到herehere的问题,但没有帮助。我们如何处理这个问题?
编辑:所以它是一个对象数组。
输入:

A
 - C
 - B

Output:

A
 - B
 - C


问题是,如果我有孙子孙女,现有的实现不会对其进行排序。

u0njafvf

u0njafvf1#

我真的不知道下面是不是你正在寻找的,但如果不是,也许你可以调整它以适应你的需要。

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)将每个两元素数组Map到数组的最后一个元素。

vxbzzdmp

vxbzzdmp2#

我试着回答了这个问题here。我认为解决方案通过将以下内容添加到acts_as_nested_set的模型中来实现您想要的功能:

def sorted_heir_list(target = self, set = self.descendants)
    sorted_list = [target]
    kids = set.select{|i| i.parent_id == target.id}.sort_by{|j| j.name}
    kids.each do |k|
      sorted_list.concat(sorted_heir_list(k, set))
    end
    sorted_list
  end

字符串
因此,调用category.sorted_heir_list给出了一个按名称排序的平面对象数组,同时保留了层次结构,并且只会导致一次DB命中。

相关问题