Изменяющая переменная, установленная в массиве find_all, похоже, изменяет исходный массив в Ruby - PullRequest
0 голосов
/ 22 октября 2009

Благодаря помощи в предыдущем вопросе я получил следующий код, возвращающий ожидаемые результаты с 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 - просто фильтр.

Есть ли способ выполнить ту же функцию, что и find all, с помощью map / collect, чтобы он создавал новый массив, который не влияет на оригинал? Мой мозг колотится, пытаясь решить это сегодня!

РЕДАКТИРОВАТЬ: Давайте посмотрим, смогу ли я уточнить это немного.

Я использую массив голосования для хранения набора значений для каждого этапа процесса голосования (с использованием одного переносимого голоса) для каждого кандидата.

В каждом туре исключается кандидат с наименьшим количеством голосов, и следующие голоса предпочтения для этого кандидата передаются соответствующим кандидатам, готовым к следующему туру.

Однако, если существует более одного кандидата с одинаково низкими голосами, то сравниваются следующие предпочтительные голоса для каждого кандидата, и наименьшее количество голосов кандидатов сигнализирует об исключенном кандидате.

Что я пытаюсь сделать с этой частью, так это найти кандидата для исключения.

Я хочу создать новый массив, содержащий кандидатов с наименьшим количеством голосов из исходного массива, а затем добавить значение (определяемое другим сопоставленным массивом, предоставленным где-то еще).

Как только у меня появится grouped_last с новыми значениями, я снова отсортирую и проанализирую последнюю позицию.

Проблема в том, что я хочу, чтобы последний сгруппированный был автономным массивом и не влиял на исходный массив / хэш.

1 Ответ

2 голосов
/ 22 октября 2009

Ваш исходный массив представляет собой массив хэшей. 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 = [] ничего не делает; вам не нужно инициализировать переменные таким образом.

Edit: этот сеанс 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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...