在删除之前复制数组中的对象

时间:2012-10-24 21:40:09

标签: ruby reference

下面的代码循环遍历数组factor_list并检查它们是否都包含指定的变量。如果是这样,将它们从数组中移除,将它们相乘,并将相对于变量的最终结果相加。完成所有操作后,将该因子添加回数组。

temp_factor = nil
factor_list.each{|factor|
        if factor._variables.include?(variable)
            if temp_factor == nil
                temp_factor = factor
            else
                temp_factor = multiply(temp_factor, factor)
            end
            factor_list.delete(factor)
        end
    }
temp_factor = sumOut(temp_factor, variable)
factor_list << temp_factor

问题是,temp_factor在每次迭代中总是nil,即使它已在前一个循环中设置。我认为主要的问题是因为数组中的删除,所以我删除了删除测试,这解决了问题(但我的数组当然充满了垃圾)。所以我得出结论,我的temp_factor是对象的浅层副本,因此它的引用对象与原始对象一样消失了。然后我尝试使用编组技巧进行深层复制,但它没有帮助。

这就是我所拥有的,因为我无法解决问题。任何人都可以帮助我找出所有这些神话背后的机制吗?

很酷的是,你们提出了很好的建议,重写代码以避免出现问题,他们真的很有帮助!但我还在想是什么导致了上述问题?如果我能学到那些信息,那就太好了!

2 个答案:

答案 0 :(得分:3)

C ++和STL的大学时代让我很难学:从来没有修改过你正在迭代的集合。那么,为什么不尝试构建新数组而不是删除项目呢?

temp_factor = nil
new_factors = factor_list.map do |factor|
  if factor._variables.include?(variable)
    if temp_factor == nil
      temp_factor = factor
    else
      temp_factor = multiply(temp_factor, factor)
    end
    nil
  else
    factor
  end
end.compact

temp_factor = sumOut(temp_factor, variable)
factor_list = new_factors + [temp_factor]

答案 1 :(得分:2)

我真的不确定我是否理解您要使用代码实现的目标,因此如果您可以提供更多关于您希望最终结果的描述以及原因,那么它可能会有所帮助,但是基于什么我你想要做的事情,我认为你可以通过将它分成几个步骤来获得更大的清晰度:

# first, split the array into an array that matches and one that doesn't
matched, factors = factor_list.partition { |f| f._variables.include? variable }

# then call multiply with each element of the matched list on the result of
# calling it on the previous elements
temp_factor = matched.reduce { |acc, f| multiply(acc, f) }

temp_factor = sumOut(temp_factor, variable)
factor_list = factors << temp_factor

我还会重新考虑有这么多经常被重新分配的临时变量,因为在任何时候都很难跟踪它们的值 - 因此很容易引入错误。