问题
I have:
fruits = {
"orange" => {:season => "winter"},
"apple" => {:season => "winter"},
"banana" => {:season => "summer"},
"grape" => {:season => "spring"},
"peach" => {:season => "winter"},
"pineapple" => {:season => "summer"}
}
I want to get:
{
"winter"=>["orange", "apple", "peach"],
"summer"=>["banana", "pineapple"],
"spring"=>["grape"]
}
I did:
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
I get:
{
"winter"=>["grape"],
"summer"=>["grape"],
"spring"=>["grape"]
}
I couldn't figure out why adding new key/value pair with unique key would overwrite existing pair in a hash. Any help with explanation would be greatly appreciated.
回答1:
In Ruby mutable objects are passed by reference. It means that when you iterate over seasons
in each
block this line:
sorted[season] = fruits
saves to sorted[season]
a reference to fruits
, for every season. After each
loop finishes every season has a reference to the same fruits
array, which contain items calculated on the last step of the iterator. In your case, it's ["grape"]
.
回答2:
Your problem is that you reuse the same fruits
array for all the values. Even though you clear it, is is still the same array. If instead of fruits.clear
you use fruits = []
then you won't have the issue.
You can see the issue in the following as an example:
arr = ['val']
hash = {
key1: arr,
key2: arr
}
p hash # => { key1: ['val'], key2: ['val'] }
arr.clear
p hash # => { key1: [], key2: [] }
You could alternatively use sorted[season] = fruits.clone
or sorted[season] = [*fruits]
... anything that uses a new array.
You have to keep track of when you use 'mutation' methods (those that change objects in-place such as clear
) - this is a common pitfall when working with hashes and arrays
来源:https://stackoverflow.com/questions/52806431/next-key-value-pair-overwrites-the-existing-pair-in-a-hash-while-trying-to-add-p