下一个键/值对在尝试使用新键添加对时覆盖散列中的现有对
Posted
技术标签:
【中文标题】下一个键/值对在尝试使用新键添加对时覆盖散列中的现有对【英文标题】:Next key/value pair overwrites the existing pair in a hash while trying to add pair with new key 【发布时间】:2019-03-19 06:33:26 【问题描述】:我有:
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"]
我不明白为什么添加具有唯一键的新键/值对会覆盖散列中的现有对。任何解释方面的帮助将不胜感激。
【问题讨论】:
既然你已经收到你的答案,你的方法也可以改写为:fruits.group_by |k,v| v[:season] .transform_values |v| v.map(&:first)
【参考方案1】:
在 Ruby 中,可变对象是通过引用传递的。这意味着当您在 each
中迭代 seasons
时,阻止此行:
sorted[season] = fruits
保存到sorted[season]
对fruits
的引用,每个季节。在each
循环结束后,每个季节都会引用相同的fruits
数组,其中包含在迭代器最后一步计算的项目。在你的情况下,它是["grape"]
。
【讨论】:
感谢 llya 的解释! 查看this 以获得生动的演示(单击可视化执行,然后继续单击前进以继续)。 从技术上讲,ruby 是严格按值传递的。***.com/questions/22827566/…It's pass-by-value, but all the values are references
。所以这更像是一个可能令人困惑的术语问题。【参考方案2】:
您的问题是您对所有值重复使用相同的 fruits
数组。即使你清除它,它仍然是同一个数组。如果您使用fruits = []
而不是fruits.clear
,那么您将不会遇到问题。
您可以在以下示例中查看问题:
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
) - 这是使用哈希和数组时的常见缺陷
【讨论】:
非常感谢。讲解和演示对我这样的初学者真的很有帮助。以上是关于下一个键/值对在尝试使用新键添加对时覆盖散列中的现有对的主要内容,如果未能解决你的问题,请参考以下文章