递归函数中数组的奇怪行为

时间:2015-06-05 17:01:50

标签: ruby-on-rails ruby recursion

我不明白这一点,据我所知,这两段代码应该做同样的事情。但他们不是。有人可以说明为什么会这样吗?

我只是想找到文件夹中的总文件。此计数还应包括所有嵌套文件夹文件。

这是我的测试用例:

A - File 1 - File 2 - File 3 -- B - File 4 -- D - File 5 -- C - File 6

当我运行此代码段时,

def get_all_files(myfolder, filearray = Array.new)
    filearray += myfolder.myfiles.pluck(:id)
    myfolder.children.each { |c| get_all_files(c, filearray) }
    return filearray
end

它只返回3个文件。 (只有A的文件。)

当我运行此代码段时,

def get_all_files(myfolder, filearray = Array.new)
    myfolder.myfiles.pluck(:id).each do |id|
      filearray.push(id)
    end
    myfolder.children.each { |c| get_all_files(c, filearray) }
    return filearray
end

它运行适当数量的文件,即6.我认为.push+都只是普通的Ruby数组方法。那么为什么会这样呢?

2 个答案:

答案 0 :(得分:2)

+ =返回数组的新实例。您的递归没有对返回值执行任何操作,因此新实例在方法结束时死亡。

当您执行push或<<时,您正在对阵列的原始实例进行操作。这就是你看到不同行为的原因。

答案 1 :(得分:1)

试试这个:

def get_all_files(myfolder)
    folder_files   = myfolder.myfiles.pluck(:id))
    children_files = myfolder.children.each_with_object([]) do |c,a|
      a += get_all_files(c, filearray))
    end if my_folder.children.any?
    folder_files + children_files
end

问题在于您的行:

myfolder.children.each { |c| get_all_files(c, filearray) }

获取子文件,但不对它们执行任何操作。

要了解正在发生的事情,请考虑以下事项:

def a(h, x=[])
  puts h[:name]
  puts "x=#{x}, x.object_id 1 = #{x.object_id}"
  x += [1]
  puts "x=#{x}, x.object_id 2 = #{x.object_id}"
  h[:children].each do |g| 
    a(g,x)
    puts h[:name]
    puts  "x=#{x}, x.object_id 3 = #{x.object_id}"
  end
  x
end

h = { name: "Bob",
      children: [
        { name: "Marsha", children: [] },
        { name: "Bippy" , children: [] }
      ]
    }

a(h)
  # Bob
  # x=[],         x.object_id 1 = 70286033312340
  # x=[1],        x.object_id 2 = 70286033311720
  #   Marsha
  #     x=[1],    x.object_id 1 = 70286033311720
  #     x=[1, 1], x.object_id 2 = 70286033311280
  # Bob
  # x=[1],        x.object_id 3 = 70286033311720
  #   Bippy
  #     x=[1],    x.object_id 1 = 70286033311720
  #     x=[1, 1], x.object_id 2 = 70286033310660
  # Bob
  # x=[1],        x.object_id 3 = 70286033311720
  # => [1]