我的递归函数没有结束。我做错了什么?

发布于 2024-11-01 22:59:39 字数 2188 浏览 0 评论 0原文

我有一个名为文件夹的模型,它充当一棵树。在模型内部,我有一个实例方法 copy,它将文件夹从一个地方复制到另一个地方。复制文件夹时,其子文件夹也必须复制。

这是我的代码:

class Folder < ActiveRecord::Base
  acts_as_tree :order => 'name'
  before_save :check_for_parent

  def copy(target_folder)
    new_folder = self.clone
    new_folder.parent = target_folder
    new_folder.save!

    # Copy sub-folders recursively
    self.children.each do |folder|
      folder.copy(new_folder) unless folder == new_folder
    end
  end

  def check_for_parent
    raise 'Folders must have a parent.' if parent.nil? && name != 'Root folder'
  end
end

现在考虑以下情况:

Root folder-+
            |
         Folder 1-+
                  |
               Folder 2-+
                        |
                      Folder 3

当我将文件夹 1 复制到根文件夹中时,它工作正常。当我将文件夹 1 复制到文件夹 2 时,它也有效,但是当我将文件夹 1 复制到文件夹 3 时,我最终会陷入无休止的递归。在代码中:

f1 = Folder.find_by_name('Folder 1')
f3 = Folder.find_by_name('Folder 3')
f1.copy(f3) # Never stops

这段代码导致:

Root folder-+
            |
         Folder 1-+
                  |
               Folder 2-+
                        |
                      Folder 3-+
                               |
                            Folder 1-+
                                     |
                                  Folder 2-+
                                           |
                                         Folder 3-+
                                                  |
                                               Folder 1-+
                                                        |
                                                     Folder 2-+
                                                              |
                                                            Folder 3-+
                                                                     |
                                                                  Folder 1-+
                                                                           |
                                                                          Etc.

我忽略了一些微不足道的事情,但我就是无法弄清楚。我做错了什么?

I have a model called folder that acts as a tree. Inside the model I have an instance method copy that copies folders from one place to another. When copying a folder, its sub-folders also have to be copied.

This is my code:

class Folder < ActiveRecord::Base
  acts_as_tree :order => 'name'
  before_save :check_for_parent

  def copy(target_folder)
    new_folder = self.clone
    new_folder.parent = target_folder
    new_folder.save!

    # Copy sub-folders recursively
    self.children.each do |folder|
      folder.copy(new_folder) unless folder == new_folder
    end
  end

  def check_for_parent
    raise 'Folders must have a parent.' if parent.nil? && name != 'Root folder'
  end
end

Now consider the following situation:

Root folder-+
            |
         Folder 1-+
                  |
               Folder 2-+
                        |
                      Folder 3

When I copy Folder 1 in the root folder it works fine. It also works when I copy Folder 1 into Folder 2, but when I copy Folder 1 into Folder 3 I end up with endless recursion. In code:

f1 = Folder.find_by_name('Folder 1')
f3 = Folder.find_by_name('Folder 3')
f1.copy(f3) # Never stops

This code leads to:

Root folder-+
            |
         Folder 1-+
                  |
               Folder 2-+
                        |
                      Folder 3-+
                               |
                            Folder 1-+
                                     |
                                  Folder 2-+
                                           |
                                         Folder 3-+
                                                  |
                                               Folder 1-+
                                                        |
                                                     Folder 2-+
                                                              |
                                                            Folder 3-+
                                                                     |
                                                                  Folder 1-+
                                                                           |
                                                                          Etc.

I am overlooking something trivial but I just can't figure it out. What am I doing wrong??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微凉 2024-11-08 22:59:39

尝试更改方法的顺序,以便在执行递归之前它首先到达叶节点:

def copy(target_folder)
  new_folder = self.clone

  # Copy sub-folders recursively
  self.children.each do |folder|
    folder.copy(new_folder) unless folder == new_folder
  end

  new_folder.parent = target_folder
  new_folder.save!
end

您的问题是您首先将“文件夹 1”重新设置为“文件夹 3”下的父级。然后你的递归调用就会运行。当到达“文件夹 3”时,它现在将“文件夹 1”作为子项,并且循环继续。

Try changing the order of your method so that it reaches the leaf node first, before doing your recursion:

def copy(target_folder)
  new_folder = self.clone

  # Copy sub-folders recursively
  self.children.each do |folder|
    folder.copy(new_folder) unless folder == new_folder
  end

  new_folder.parent = target_folder
  new_folder.save!
end

Your problem is that you're starting by reparenting 'Folder 1' under 'Folder 3'. Then your recursive call runs. When it gets to 'Folder 3' it now has 'Folder 1' as a child, and the cycle continues.

柏拉图鍀咏恒 2024-11-08 22:59:39

尝试在实现递归(即前序递归)的循环之前复制当前文件夹。

Try doing the copying of the current folder before loop that implements the recursion (i.e. pre-order recursion).

醉城メ夜风 2024-11-08 22:59:39

我必须跟踪我最初复制的文件夹。下面的代码有效。当然,如果有人认为有改进的空间,请告诉我。

def copy(target_folder, originally_copied_folder = nil)
    new_folder = self.clone
    new_folder.parent = target_folder
    new_folder.save!

    originally_copied_folder = new_folder if originally_copied_folder.nil?

    # Copy sub-folders recursively
    self.children.each do |folder|
      folder.copy(new_folder, originally_copied_folder) unless folder == originally_copied_folder
    end
  end

I had to keep track of which folder I originally copied. The code below works. Of course, if anyone sees room for improvement, please let me know.

def copy(target_folder, originally_copied_folder = nil)
    new_folder = self.clone
    new_folder.parent = target_folder
    new_folder.save!

    originally_copied_folder = new_folder if originally_copied_folder.nil?

    # Copy sub-folders recursively
    self.children.each do |folder|
      folder.copy(new_folder, originally_copied_folder) unless folder == originally_copied_folder
    end
  end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文