0

下面的代码循环遍历一个数组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在每次迭代中,即使它已在前一个循环中设置。我认为主要问题是因为数组中的删除,所以我删除了删除进行测试,并且解决了问题(但我的数组当然充满了垃圾)。所以我得出的结论是 mytemp_factor是对象的浅拷贝,因此它的引用对象与原始对象一起消失了。然后我尝试使用 marshal 技巧进行深度复制,但没有帮助。

这就是我所拥有的,因为我无法解决问题。谁能帮我找出所有这些神话背后的机制?

你们就重写代码以避免问题提供了非常好的建议,这很酷,他们真的很有帮助!但我仍然想知道是什么导致了上述问题?如果我能学到那一点信息就太好了!

4

2 回答 2

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]
于 2012-10-24T21:46:22.750 回答
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

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

于 2012-10-24T22:05:31.733 回答