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

时间:2018-10-14 19:40:36

标签: ruby ruby-hash

我有:

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 个答案:

答案 0 :(得分:1)

您的问题是您对所有值重复使用相同的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.clonesorted[season] = [*fruits] ...使用新数组的任何东西。

您必须跟踪何时使用'mutation'方法(那些在原处更改对象的方法,例如clear)-这是使用哈希和数组时的常见陷阱

答案 1 :(得分:1)

在Ruby中,可变对象是通过引用传递的。这意味着当您在seasons中的each上进行迭代时,请阻止此行:

sorted[season] = fruits

每个季节都将对sorted[season]的引用保存到fruits。在each循环结束之后,每个季节都将引用相同的fruits数组,其中包含在迭代器的最后一步中计算出的项。您的情况是["grape"]