7 Interesting Ruby Array Methods

6 Min. Read
Sep 8, 2019

Arrays are one of the fundamental structures of programming. Being able to quickly manipulate and read data out of them is vital to success in building stuff with computers. Here are seven methods you can’t do without:

Map/Each

These two methods are very similar. They allow you to step through “each” item in an array and do something to it.

Check out some code:

1
2
3
array = [1, 2, 3]
effects = array.each{|x| # create record from x }
added = array.map{ |x| x + 2 }

If we read from added, we’ll get [3, 4, 5]. If we read from effects, we’ll still get [1, 2, 3]. Here’s the difference between these two: .map will return a new modified array, whereas .each will return the original array.

Ruby’s .map might seem a little strange. To give off a clearer view look at this example.7

1
2
3
4
5
6
7
8
9
# we create an array of records
array = [e, e2, e3]
# => [#<Event id: 1, name: nil>, #<Event id: 2, name: nil">, #<Event id: 3, name: nil>]
# so far so good
new_array = array.map{|e| e.name = "a name"; e}
# => [#<Event id: 1, name: "a name">, #<Event id: 2, name: "a name">, #<Event id: 3, name: "a name">]
# uh-oh, that ain't right
array
# => [#<Event id: 1, name: "a name">, #<Event id: 2, name: "a name">, #<Event id: 3, name: "a name">]

We might expect that we are working with some kind of copy of our records in the array, but we are not. That is all just to say: be careful. You can easily create side effects in your .map functions.

Select

.select allows you to “find” an element in an array. You have to give .select a function that returns true or false, 7 so it knows whether or not to “keep” an array element.

1
2
3
array = ['hello', 'hi', 'goodbye']
array.select{|word| word.length > 3}
# => ["hello", "goodbye"]

A slightly more complex example, probably getting closer to how you’d actually use this. Let’s throw in .map at the end for good measure:

1
2
3
4
valid_colors = ['red', 'green', 'blue']
cars = [{type: 'porsche', color: 'red'}, {type: 'mustang', color: 'orange'}, {type: 'prius', color: 'blue'}]
cars.select{ |car| valid_colors.include?(car[:color]) }.map{ |car| car[:type]}
# => ["porsche", "prius"]

Yes, you can indeed join these methods to wield unimaginable power.

Reject

Reject is the yin to .select’s yang:

1
2
cars.reject{|car| valid_colors.include?(car[:color]) }.map{|car| car[:type]}
# => ["mustang"]

Instead of selecting for the array items we want, we will reject everything that does not make our function return true. Remember that the function inside our reject is what determines if the array item will be returned or not — if it’s true, the item is returned, otherwise not.

Reduce

Reduce has a more complex structure than our other array methods, but it’s generally used for pretty simple things in Ruby — mostly math stuff. We’ll take an array, then run a function on every item in that array. This time, we care about what is being returned from the other array items. Typically we are adding up a bunch of numbers:

1
2
3
array = [1, 2, 3]
array.reduce{|sum, x| sum + x}
# => 6

Note that we can work with strings in the same way:

1
2
3
array = ['amber', 'scott', 'erica']
array.reduce{|sum, name| sum + name}
# => "amberscotterica"

This might be helpful if we are looking at a bunch of work records. If we need to add up total hours worked, or if we want to find out the sum of all donations last month. One final note about .reduce. is if you’re working with anything other than regular old numbers (or strings), you’ll need to include a starting value as an argument:

1
2
3
4
5
array = [{weekday: 'Monday', pay: 123}, {weekday: 'Tuedsay', pay: 244}]
array.reduce(0) {|sum, day| sum + day[:pay]}
# => 367
array.reduce(100) {|sum, day| sum + day[:pay]}
# => 467

Join

Talking about .join as a bonus because it’s so dang useful. Let’s use our array cars again:

1
2
cars.map{|car| car[:type]}.join(', ')
# => "porsche, mustang, prius"

.join is a lot like .reduce except it’s got a super-clean syntax. It takes one argument: a string that will be inserted between all array elements. .join creates one long string out of whatever you give it, even if your array is a bunch of non-string stuff:

1
2
3
4
cars.join(', ')
# => "{:type=>\"porsche\", :color=>\"red\"}, {:type=>\"mustang\", :color=>\"orange\"}, {:type=>\"prius\", :color=>\"blue\"}"
events.join(', ')
# => "#<Event:0x007f9beef84a08>, #<Event:0x007f9bf0165e70>, #<Event:0x007f9beb5b9170>"

Slice

slice is a method that operates on arrays, strings, and (since Ruby 2.5.0) hashes. We’ll just focus on arrays for now, since the logic is basically the same regardless, but keep in mind that you can call slice on strings and hashes as well. slice allows you to cut into an array and select specific elements.

Let’s say you have an array of fruits:

fruit = [“apple”, “banana”, “orange”, “grapefruit”, “tomato”]

You can call slice on the array, pass it a specific index, and it will return the object at that index. Calling fruit.slice with an argument of (2) will return the string object “orange” because “orange” is at index 2 of the fruit array (note that array elements are indexed starting at 0, so “apple” is at index 0, “banana” is at index 1, etc). Let’s drop into IRB and check it out:

1
2
3
4
fruit = ["apple", "banana", "orange", "grapefruit", "tomato"]
# => ["apple", "banana", "orange", "grapefruit", "tomato"]
fruit.slice(2)
# => "orange"

If you want the banana, the orange, and the grapefruit, you can call slice with a starting index and a length of elements and it will return those objects in an array.

1
2
3
4
fruit = ["apple", "banana", "orange", "grapefruit", "tomato"]
# => ["apple", "banana", "orange", "grapefruit", "tomato"]
fruit.slice(1,3)
# => ["banana", "orange", "grapefruit"]

This selects all elements starting with index 1 and ending with index 3.

Similarly, we can use a range

1
2
fruit.slice(1..3)
# => ["banana", "orange", "grapefruit"]

Cycle

cycle is a Array class method which returns the array by calling the given block each time for every element in the array ‘n’ no. of times and if ‘nil’ is given, then it will call it for forever.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# declaring array
a = [18, 22, 33, 5, 6]

# declaring array
b = [1, 4, 1, 1, 88, 9]

# declaring array
c = [18, 22, nil, nil, 50, 6]

# cycling the array elements
puts "cycle : #{a.cycle(3){ |x| puts x*x }}\n\n"

# cycling the array elements
puts "cycle : #{b.cycle(2){|x| puts x}}\n\n"