Следующая пара ключ / значение перезаписывает существующую пару в хэше при попытке добавить пару с новым ключом
Я имею:
fruits = {
"orange" => {:season => "winter"},
"apple" => {:season => "winter"},
"banana" => {:season => "summer"},
"grape" => {:season => "spring"},
"peach" => {:season => "winter"},
"pineapple" => {:season => "summer"}
}
Я хочу получить:
{
"winter"=>["orange", "apple", "peach"],
"summer"=>["banana", "pineapple"],
"spring"=>["grape"]
}
Я сделал:
def sort_fruits(fruits_hash)
fruits=[]
sorted = {}
seasons = fruits_hash.map {|k, v|v[:season]}
seasons.uniq.each do |season|
fruits.clear
fruits_hash.each do |fruit, season_name|
if season == season_name[:season]
fruits << fruit
end
end
p sorted[season] = fruits ## season changes to new season, so this should have created new key/value pair for new season.
end
sorted
end
Я получил:
{
"winter"=>["grape"],
"summer"=>["grape"],
"spring"=>["grape"]
}
Я не мог понять, почему добавление новой пары ключ / значение с уникальным ключом перезапишет существующую пару в хеш. Любая помощь с объяснением будет принята с благодарностью.
2 ответа
В Ruby изменяемые объекты передаются по ссылке. Это означает, что когда вы перебираете seasons
в each
заблокировать эту строку:
sorted[season] = fruits
сохраняет в sorted[season]
ссылка на fruits
на каждый сезон. После each
цикл заканчивается каждый сезон имеет ссылку на то же самое fruits
массив, содержащий элементы, рассчитанные на последнем шаге итератора. В вашем случае это ["grape"]
,
Ваша проблема в том, что вы используете то же самое fruits
массив для всех значений. Даже если вы очистите его, это все тот же массив. Если вместо fruits.clear
ты используешь fruits = []
тогда у вас не будет проблемы.
Вы можете увидеть проблему в следующем примере:
arr = ['val']
hash = {
key1: arr,
key2: arr
}
p hash # => { key1: ['val'], key2: ['val'] }
arr.clear
p hash # => { key1: [], key2: [] }
Вы могли бы альтернативно использовать sorted[season] = fruits.clone
или же sorted[season] = [*fruits]
... все, что использует новый массив.
Вы должны отслеживать, когда вы используете методы "мутации" (те, которые изменяют объекты на месте, такие как clear
) - это распространенная ошибка при работе с хешами и массивами