Попытка сохранить этот оригинальный массив терпит неудачу здесь - PullRequest
1 голос
/ 29 января 2020

У меня есть этот код ниже

resultOfAllScenarios=[[[1,2],[3,4]],[[1,2],[3,4]],[[1,2],[3,4]]]
arr = resultOfAllScenarios
arr.each do |value|
  value.delete_if { |x|x.sum>3 }
end

p resultOfAllScenarios

Вывод

[[[1, 2]], [[1, 2]], [[1, 2]]]

Я копирую resultOfAllScenarios в arr, но исходный массив все еще мутирован. Поэтому я клонировал массив, как показано ниже

resultOfAllScenarios=[[[1,2],[3,4]],[[1,2],[3,4]],[[1,2],[3,4]]]
arr = resultOfAllScenarios.clone
arr.each do |value|
  value.delete_if { |x|x.sum>3 }
end

p resultOfAllScenarios

Вывод

[[[1, 2]], [[1, 2]], [[1, 2]]]

Но исходный массив все же мутировал. Кажется, что это не клонирование внутреннего массива. Что я должен сделать, чтобы сохранить исходный массив? Кто-нибудь может мне помочь?

Ответы [ 2 ]

1 голос
/ 29 января 2020

Согласно документам:

Массив изменяется мгновенно при каждом вызове блока, а не после окончания итерации.

С этим я могу Предположим, что исходный массив всегда будет изменен. Проверьте, что после использования clone все элементы в приемнике заканчиваются одинаково:

foo = [[1,2], [3,4], [5,6]]
p foo.map(&:object_id)
# [70238411027480, 70238411027460, 70238411027440]
bar = foo.clone
p bar.map(&:object_id)
# [70238411027480, 70238411027460, 70238411027440]

Итак, когда вы используете delete_if, вы модифицируете эти объекты, независимо от того, клонировали ли вы их.

Что я должен сделать, чтобы сохранить исходный массив? Может быть, вы можете просто использовать reject, чтобы избежать мутации объекта без лишних операций:

resultOfAllScenarios=[[[1,2],[3,4]],[[1,2],[3,4]],[[1,2],[3,4]]]
arr = resultOfAllScenarios.map do |value|
  value.reject { |x|x.sum>3 }
end
1 голос
/ 29 января 2020

Когда вы делаете:

arr = resultOfAllScenarios

Вы в основном ссылаетесь на память массива, а не на его копию. Сделайте clone вместо:

arr = resultOfAllScenarios.map(&:clone)

Что здесь происходит?:

arr = resultOfAllScenarios
pp resultOfAllScenarios.map(&:object_id) 
#=> [70173532995400, 70173532994980, 70173532994220]
pp arr.map(&:object_id)
#=> [70173532995400, 70173532994980, 70173532994220]

Но когда вы clone подмассивы:

arr = resultOfAllScenarios.map(&:clone)

pp resultOfAllScenarios.map(&:object_id) 
#=> [70154004258860, 70154004274800, 70154004272760]

pp arr.map(&:object_id) 
#=> [70154004271580, 70154004271240, 70154004271120]

Итак, arr теперь содержит ссылки на новые объекты, клонированные из resultOfAllScenarios в последнем примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...