Move and change
eachin a bunch of places, so we'll start off with an
each_with_index. With this you can define blocks with two arguments, the element (just like
each) and its index.
We know about the
Enumerable module and its purpose. Any class that mixes in
Enumerable has access to all its methods.
Hash in Ruby, just like
Array, also includes
The first argument in the
each_with_index block for hashes would contain the key-value pair as an array, the second being the pair's position in the hash. Hashes in Ruby are funny that way - iterating over a
Hash almost always gives you the key and value in an
map is another
Enumerable method that is similar to
each. It goes through each element in your
Hash and evaluates the block for that element and appends the value in an array that it returns.
In other words,
each is used for simple iteration,
map for transformation. In the example below, we will transform the original array, producing a new one that contains all the values of the original incremented by 1.
map returns the resultant array.
each returns the original array.
The purpose of
map is to return this resultant array created when the operations are applied to the original data structure -- which obviously makes its return value useful.
each is more of a generic iterator that is often used to
puts things out. Because of the simple nature of
each, it is also used as a custom iterator builder.
Exploit the fact that
map always returns an array: write a method
hash_keys that accepts a hash and maps over it to return all the keys in a linear
injectis a powerful enumerator that can do iteration (walking over all items in a collection), accumulation and transformation all at once. Here's an example using an
0argument to the
inject(0)method is an optional default value.
This optional default value is assigned to the first argument
accumulatorin the block. If there is no value, then
accumulatorstarts with the first value of the array. This is done only once on the first iteration.
injectis also an iterator, the second argument
iteratedbeing the element it's currently on.
accumulatorhere, is basically incrementing itself by adding the value of
If you find this hard to wrap your head around, then here's a more broken down version of what
inject essentially does, using
each. It takes the
Array and an optional default value, and assigns that default value to a local variable
accumulator. It assigns the first element of the array if there is no default value, i.e. it's
nil. It then loops through the
array and increments the local variable
accumulator and finally returns the new value of
injectgreatly simplifies the amount of code you write when you're building values and iterating at the same time. Building a
Arrayis a pretty common use case.
Try implementing a method called
occurrences that accepts a string argument and uses
inject to build a
Hash. The keys of this hash should be unique words from that string. The value of those keys should be the number of times this word appears in that string.
inject method is also aliased to