修改变量set to array find_all似乎修改了Ruby中的原始数组

时间:2009-10-22 16:30:05

标签: ruby arrays

感谢a previous question中的帮助,我有以下代码返回find_all的预期结果。

原始数组(按投票[0]排序):

votes_array = [{"votes"=>[13], "id"=>"4", "elected"=>0}, {"votes"=>[12], "id"=>"1", "elected"=>0}, {"votes"=>[8], "id"=>"3", "elected"=>0}, {"votes"=>[3], "id"=>"2", "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]

在此数组之后运行的代码:

grouped_last = []
grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }
if grouped_last.length > 1
  grouped_last.each do |candidate|
    candidate["votes"][0] += 10 # another value is actually inserted here
  end
end

问题在于它正在影响原始数组 - 因为我认为应该这样,因为find_all只是一个过滤器。

有没有办法执行与使用map / collect查找all相同的功能,以便创建一个不影响原始数据的新数组?我的大脑今天试图解决这个问题!

编辑:让我们看看我是否可以澄清这一点。

我正在使用votes_array为每个候选人的投票过程的每个阶段(使用单一可转让投票)存储一组值。

对于每一轮,具有最低选票的候选人被淘汰,并且该候选人的下一个偏好投票将被转移到准备好进入下一轮的相关候选人。

然而,如果有多个候选人拥有相同的最低票数,那么将比较每个候选人的下一个偏好投票,并且最低候选人投票数表示被淘汰的候选人。

我要对这部分做的是找到要消除的候选人。

我想创建一个包含原始数组中最低投票候选者的新数组,然后添加一个值(由其他地方提供的另一个映射数组确定)。

然后,当我使用新值进行分组时,我将对最后位置进行排序和分析。

问题是我希望最后分组为独立数组,而不会影响原始数组/哈希。

1 个答案:

答案 0 :(得分:2)

原始数组是一个哈希数组。 find_all返回一个新数组,但该数组的内容是对原始哈希的引用。试试这个:

def deep_copy(obj)
  Marshal.load(Marshal.dump(obj))
end

grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }
grouped_last = deep_copy(grouped_last)

另外,grouped_last = []什么都不做;你不需要那样初始化变量。

编辑:这个irb会话应该更清楚地发生了什么:

>> votes_array.map {|x| x.object_id}
=> [80823078, 80822924, 80822784, 80822644, 80822504]

>> grouped_last = votes_array.find_all {|i| i["votes"][0] ==  votes_array.last["votes"][0] }
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]

>> grouped_last.map {|x| x.object_id}
=> [80822644, 80822504]

>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }.dup

=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]
>> grouped_last.map {|x| x.object_id}

=> [80822644, 80822504]
>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }.map {|x| x.dup}

=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]
>> grouped_last.map {|x| x.object_id}
=> [81390302, 81390288]

>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]

>> grouped_last = deep_copy(grouped_last)
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]

>> grouped_last.map {|x| x.object_id}
=> [80366188, 80362338]