-
Notifications
You must be signed in to change notification settings - Fork 10
Enumerable
Standard Enumerable#map
has a great shortcut when you want to create an Array
by calling a method on each element in the collection. For example:
class Pokemon
attr_accessor :name
def initialize(n)
@name = n
end
end
your_pokedex = [
Pokemon.new("Bulbasaur"),
Pokemon.new("Charmander"),
Pokemon.new("Squirtle"),
]
If you want an Array
of Pokemon names, you use Enumerable#map
:
your_pokedex.map { |p| p.name }
# => ["Bulbasaur", "Charmander", "Squirtle"]
A shortcut makes it easy for trivial, repeatable method calls (such as to :name
):
your_pokedex.map(&:name)
# => ["Bulbasaur", "Charmander", "Squirtle"]
But what happens when my Pokedex isn't as well-structured as yours?
my_pokedex = [
{name: "Bulbasaur"},
{name: "Charmander"},
{name: "Squirtle"},
]
I can still map the :name
keys out to an Array
with full block notation...
my_pokedex.map { |p| p[:name] }
# => ["Bulbasaur", "Charmander", "Squirtle"]
But such sad! I can haz no shortcut.
my_pokedex.map(??????)
# => ["Bulbasaur", "Charmander", "Squirtle"]
Enter Enumerable#key_map
:
my_pokedex.key_map(:name)
# => ["Bulbasaur", "Charmander", "Squirtle"]
Building off of Enumerable#key_map
, finishing_moves provides a convenience method when you need to perform a one-step map/reduce operation on a collection.
my_pokedex = [
{name: "Bulbasaur", level: 2},
{name: "Charmander", level: 2},
{name: "Squirtle", level: 2},
]
In other words, this map/reduce operation
my_pokedex.key_map(:level).reduce(0) { |memo,lvl| memo + lvl }
# => 6
can be simplified to
my_pokedex.key_map_reduce(:level, :+)
# => 6
where :+
can be any named method of memo
, and is applied to each value (just as in Enumerable#reduce
). For additional flexibility, you can pass an intial value for memo
and a custom block
(and again, this works just like Enumerable#reduce
):
my_pokedex.key_map_reduce(:level, 0) { |memo,lvl| memo + lvl }
# => 6