ruby

Two Ruby patterns around map and reduce

When you're going to choose a method to work to transform a group of n things in Ruby, there are two broad patterns you can choose: work with a map function or work with a reduce / inject function.

This pattern choice was recently explained to me as part of my Ruby education at Launch School. I hadn't fully grokked that the choice around how you transform a bundle of things (an Array, perhaps) really can be summarised by those two options.

You use a map method when you want to transfer your array into another array of (transformed) things. (For example, you wanted to transform an array of lowercase names into an array of uppercase names).

example_array = ['alex', 'john', 'terry', 'gill']
transformed_array = example_array.map(&:upcase) # => ["ALEX", "JOHN", "TERRY", "GILL"]

You use a reduce method when you want to transform n number of things (inside your array) into a single thing. (For example, you wanted to sum up the values of an array).

example_array = [1, 3, 5, 7, 9]
transformed_array = example_array.reduce(:+) # => 25

Using Ruby's .digits method

I discovered the .digits method in Ruby the other day. As a quick illustration, it extracts the digits of a method into an array, reverse sorted.

12345.digits #=> [5, 4, 3, 2, 1]

You can optionally specify what base you’d like it to use to calculate the digits using, i.e. the same calculation as above but in base 100 would give you the following:

12345.digits(100) #=> [45, 23, 1]

Reading around a little bit, it seems that if you’re trying to get hold of the digits of a number, simply doing a .digits.reverse is perhaps an ok solution if the number is small, but at a certain point it starts to get slow. This is because .digits isn’t just ‘splitting’ the number.

For that reason, perhaps using .to_s.chars might be a better alternative. You can then use a .map function to convert the characters into integers:

12345.to_s.chars.map { |digit| digit.to_i }

I’m not entirely sure what .digits is actually used / useful for, given the speed issues.

Using Ruby's .zip method to combine arrays

In Ruby, zip is a way to combine elements from two different arrays, albeit in a way that is slightly difficult to understand at first glance.

The documentation is a bit opaque, at least to my eyes, and the examples given take a bit of time to get your head around.

Let’s say you had an array of fruits that you wanted to distribute to your friends. You’re organised, so you have a list of your friends as well.

fruits = ["mango", "orange", "pomegranate"]
friends = ["Rob", "Mary", "Holly"]

Using multiple methods and loops, it’d be fairly trivial to conjure up something to combine these two into a new array, but luckily for us .zip exists to save the day.

friends.zip(fruits)

will return:

[["Rob", "mango"], ["Mary", "orange"], ["Holly", "pomegranate"]]

This way everyone will know what fruit they’re getting.

Note that if one of the two arrays is longer / shorter than the other, the missing space(s) will be filled with nil values.