【问题标题】:Amending variable set to array find_all seems to amend original array in Ruby修改设置为数组 find_all 的变量似乎修改了 Ruby 中的原始数组
【发布时间】:2009-10-22 16:30:04
【问题描述】:

感谢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 执行与 find all 相同的功能,以便创建一个不影响原始数组的新数组?今天想解决这个问题,我的大脑在嘶嘶作响!

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

我正在使用 votes_array 为每个候选人的投票过程的每个阶段(使用 Single Transferrable Vote)存储一组值。

在每一轮中,票数最低的候选人被淘汰,该候选人的下一个优先票将转移给准备下一轮的相关候选人。

但是,如果有多个候选人的最低票数相同,则会比较每个候选人的下一个偏好票,并且候选人票数最低的候选人表示被淘汰。

我试图用这部分做的是找到要淘汰的候选人。

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

一旦我用新值分组_last,我将再次排序和分析最后一个位置。

问题是我希望最后分组成为一个独立的数组并且不影响原始数组/哈希。

【问题讨论】:

  • 我不确定您在此处尝试在预期结果方面做什么。
  • 我希望澄清对 tadman 有所帮助?

标签: ruby arrays


【解决方案1】:

您的原始数组是一个哈希数组。 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]

【讨论】:

  • 请注意,因为 votes 数组没有被克隆,仍然是对原始数组的引用。 dup 方法并不像你想象的那样“深度克隆”,而是只复制第一层。
  • 哎呀,是的,我认为数组内容是一个平面哈希,所以 dup 可以正常工作。没有注意到有些值本身就是数组。
猜你喜欢
  • 1970-01-01
  • 2019-07-27
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 2014-07-15
  • 2012-11-28
  • 1970-01-01
相关资源
最近更新 更多