如何递归搜索自引用子主题?

时间:2009-09-14 21:41:02

标签: ruby recursion

如果我有一个自引用的Topic类,并且我想递归遍历所有的子主题,那么Ruby的方法是什么呢?

@category.topics.all(:parent_id => topic.id).each do |subtopic|
    subtopic.delete_tags
    @category.topics.all(:parent_id => subtopic.id).each do |subsubtopic|
    subsubtopic.delete_tags
        @category.topics.all(:parent_id => subsubtopic.id).each do |subsubsubtopic|
        subsubtopic.delete_tags
            @category.topics.all(:parent_id => subsubsubtopic.id).each do |subsubsubsubtopic|
            subsubsubtopic.delete_tags
            end
        end
    end
end

3 个答案:

答案 0 :(得分:1)

这样的东西?

class Topic
  def delete_subtopic_tags
    all(:parent_id => self.id).each do |subtopic|
      subtopic.delete_subtopic_tags
      subtopic.delete_tags
    end
  end
end

答案 1 :(得分:1)

这是一个ActiveRecord模型类吗?如果是这样,您应该能够使用类似下面的代码干净地通过子对象进行递归:

class Topic
  has_many :topics
  belongs_to :parent, :classname => "Topic", :foreign_key => 'parent_id'

  # ...other model class logic...
  def delete_tags_recursive
    delete_tags
    topics.each {|subtopic| subtopic.delete_tags_recursive }
  end
end

这样做的另一个好处是,您可以使用由topicsparent装饰器创建的has_manybelongs_to方法,以便轻松浏览主题树。< / p>

答案 2 :(得分:0)

我不知道Ruby,但是如果你有哈希表和链表实现方便我会这样做(在Java-ish伪代码中):

Topic currentTopic = topic;
list.add(currentTopic);
hashtable.add(currentTopic);
while (list.empty() == false) {
    for (Topic t : currentTopic.getSubtopics()) {
        if (hashtable.contains(t) == false) {
            list.add(t);
            hashtable.add(t);
        }
    }
    visit(currentTopic);
    list.remove(currentTopic);
    currentTopic = list.getFirst();
}

这里的主要观点是保留哈希表列表,以便您可以轻松确保从未访问过两次主题。除此之外,它基本上是breadth-first search的实现。 visit()会针对每个主题执行您需要做的任何事情。