下一个键/值对在尝试使用新键添加对时覆盖散列中的现有对

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(&amp;: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.clonesorted[season] = [*fruits] ... 任何使用新数组的东西。

您必须跟踪何时使用“变异”方法(那些就地更改对象的方法,例如 clear) - 这是使用哈希和数组时的常见缺陷

【讨论】:

非常感谢。讲解和演示对我这样的初学者真的很有帮助。

以上是关于下一个键/值对在尝试使用新键添加对时覆盖散列中的现有对的主要内容,如果未能解决你的问题,请参考以下文章

Java HashMap原理

如何根据散列中的键/值查找键/值数据并将其添加到 Redis 中的散列?

PySpark - 创建键值对时丢失字符串值

迭代时无意中将键添加到哈希

学习python第六天-字典学习

文件中存在重复键值对时如何读取属性文件?