One of the most useful Ruby methods I've learned about so far at Dev Boorcamp is the #map method of the enumerable class. This method iterates through an array or hash, running a code block on each element and returning an array or hash of the altered values. A quick demonstration to drive things home is always nice:
> [1,2,3,4,5,6,7,8].map {|x| x + 100}
=> [101, 102, 103, 104, 105, 106, 107, 108]
Running the above code in IRB will iterate through each of the array elements and add 100 to each of them. The |x| portion of the line of code is setting x as the code block's variable which, in this case, corresponds to the current element in an array as it's being iterated over. Arrays are pretty easy-peasy with the map method, but-
Using the #map method on a hash is pretty similar to an array, spare 3 key (no pun intended) differences:
1. The map's code block variable needs a buddy. Each iteration of an array just contained a single object, but each iteration of a hash has 2- one for the key and one for the value. This means the map method code block needs a variable for each. Ruby developers commonly use |k, v|, where "k" is the key and "v" is the value.
2. The code after the block variables needs to be in those cute little curly brackets or else your code will throw errors.
… and I can't remember what #3 was. Oh well, moving forward. Once again, a demonstration is worth a thousand words. Unless the demonstration is already a thousand words, then it's worth like a billion or something.
> hash = {"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5, "six"=>6}
> hash.map{ |k, v| { k => v + 100 } }
=> [{"one"=>101}, {"two"=>102}, {"three"=>103}, {"four"=>104}, {"five"=>105}, {"six"=>106}]
Hold the phone. The output looks like it's actually an array? Ah, that's right- that's what key difference #3 was.
3. Using #map on a hash will output an array version of the hash.
While you can hack this array of key/value pairs to be usable, it definitely isn't ideal because it won't behave like a normal hash. I found a really handy-dandy solution to this that requires you to extend the standard Hash class in Ruby. No worries, it's not as scary as it sounds.
class Hash
def hmap(&block)
Hash[self.map {|k,v|| block.call(k,v) }]
end
end
This new method looks like this in practice-
> hash.hmap{ |k,v| [ k => v + 100 ] }
=> {"one"=>101, "two"=>102, "three"=>103, "four"=>104, "five"=>105, "six"=>106}
That's hot biscuits, right? Special thanks to Chris Holtz for the great #hmap method.