2

I am trying to update my hash's values after subtracting the values by three. For example,

extinct_animals = {
  "Passenger Pigeon" => 1914,
  "Tasmanian Tiger" => 1936,
  "Eastern Hare Wallaby" => 1890,
  "Dodo" => 1662,
  "Pyrenean Ibex" => 2000,
  "West African Black Rhinoceros" => 2011,
  "Laysan Crake" => 1923
}

I have this code, which sets the values to subtract three:

extinct_animals.each {|animal, year| puts year - 3}

and the output:

1911
1933
1887
1659
1920

How do I return the entire hash with the keys and new values?

sawa
  • 165,429
  • 45
  • 277
  • 381
jmk929
  • 45
  • 1
  • 5
  • 1
    Possible duplicate of [How to change Hash values?](https://stackoverflow.com/questions/812541/how-to-change-hash-values) – anothermh Dec 19 '18 at 02:39
  • @anothermh, a dup? Yes, I think so, but it nicely illustrates the pitfalls of closing a question for that reason. In this case the method `transform_values!` would not make it into the Ruby core until eight years after the original question was asked. Also, we've all seen answers offered to questions that were far superior to the answers given to the earlier question. Of course, the great answer could always be added to those given to the duped question, but it won't have much visibility, particularly when, as here, the duped question is ancient. I don't have an answer, but it is a problem. – Cary Swoveland Dec 19 '18 at 03:50
  • @CarySwoveland I would prefer seeing this question closed as a duplicate so users are directed to the one linked above, where you will find `transform_values` as the second highest voted answer with a score of 61. It would seem that the issue of "visibility" for that answer is non-existent; I don't agree that there is any problem with closing this. – anothermh Dec 19 '18 at 04:00
  • I hadn't noticed that answer, which was submitted eight years after the question wss posted, but yes, you have a point. – Cary Swoveland Dec 19 '18 at 06:13

2 Answers2

5

You'll want to use Hash#transform_values!, which made its debut in MRI v2.4:

extinct_animals.transform_values! { |v| v - 3 }
  #=> {"Passenger Pigeon"=>1911, "Tasmanian Tiger"=>1933,
  #    "Eastern Hare Wallaby"=>1887, "Dodo"=>1659, "Pyrenean Ibex"=>1997,
  #    "West African Black Rhinoceros"=>2008, "Laysan Crake"=>1920}

extinct_animals
  #=> {"Passenger Pigeon"=>1911, "Tasmanian Tiger"=>1933,
  #    "Eastern Hare Wallaby"=>1887, "Dodo"=>1659, "Pyrenean Ibex"=>1997,
  #    "West African Black Rhinoceros"=>2008, "Laysan Crake"=>1920}
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
0

Within the block, make sure you are modifying the hash by using =:

extinct_animals.each { |animal, year| extinct_animals[animal] = year - 3 }
=> {
  "Passenger Pigeon" => 1911,
  "Tasmanian Tiger" => 1933,
  "Eastern Hare Wallaby" => 1887,
  "Dodo" => 1659,
  "Pyrenean Ibex" => 1997,
  "West African Black Rhinoceros" => 2008,
  "Laysan Crake" => 1920
}

Don't use puts. That just writes out to the console.

A more brief version of this solution would be:

extinct_animals.each { |animal, _year| extinct_animals[animal] -= 3 }

Here we prefix year with an underscore to indicate that the variable is not used within the block.

anothermh
  • 9,815
  • 3
  • 33
  • 52