Day 03 - Array Methods in Ruby

Day 03 - Array Methods in Ruby

How to manipulate elements in arrays with handy methods

Methods are so handy when you play with arrays in Ruby. Here are some useful methods I used while doing the Codewars challenge.

chars()

chars returns an array of characters in strings. This is a shorthand for each_char.to_a. Let's take a look at these 2 methods separately.

each_char()

each_char passes each character in the string to the given block, or returns an enumerator if no block is given.

"hello".each_char {|c| print c, ' ' }
#=> h e l l o

One thing worth mentioning is that each_char is quite similar to each method in Ruby.

The difference is that you can pass an argument to each for splitting the string but you can't do the same with each_char .

The argument will be passed to the supplied block as the record separator ($/ by default). If no record separator is provided, the string is split into paragraphs delimited by multiple successive newlines.

You can check the example below:

# Example one
"hello\nworld".each {|s| p s}
#=>  "hello\n"
#=>  "world"

# Example Two
"hello\nworld".each('l') {|s| p s}
#=>  "hel"
#=>  "l"
#=>  "o\nworl"
#=>  "d"

# Example Three
"hello\n\n\nworld".each('') {|s| p s}
#=>  "hello\n\n\n"
#=>  "world"

to_a()

to_a simply turns the obj into an array.

"hello".to_a    #=> ["hello"]
Time.new.to_a   #=> [39, 54, 8, 9, 4, 2003, 3, 99, true, "CDT"]

Combine two into one

Therefore, chars is the easiest and cleanest way to turn a string into an array without passing anything by combining the power of each_char and to_a.

"abcdef".chars
#=> ["a", "b", "c", "d", "e", "f"]

include?()

When you want to check whether an item is stored inside the array, the best method is to use include? . It turns true if the given object is present in self (that is if any element == object), otherwise returns false.

a = [ "a", "b", "c" ]
a.include?("b")   #=> true
a.include?("z")   #=> false

#These also work
a.include? "b"    #=> true
a.include? "z"    #=> false

uniq()

uniq is super useful when you need to remove duplicate values in an array. It returns a new array without repeated items.

You can also pass a block to it and it then will use the return value of the block for comparison.

a = [ "a", "a", "b", "b", "c" ]
a.uniq   # => ["a", "b", "c"]

b = [["student","sam"], ["student","george"], ["teacher","matz"]]
b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]

sort()

sort returns a new array created by sorting self. You can also pass a block to it by using the <=> operator.

The block must implement a comparison between a and b and:

  1. return an integer less than 0 when b follows a ,

  2. return 0 when a and b are equivalent, or

  3. return an integer greater than 0 when a follows b.

Please remind the result is not guaranteed to be stable. When the comparison of two elements returns 0, the order of the elements is unpredictable.

ary = [ "d", "a", "e", "c", "b" ]
ary.sort                     #=> ["a", "b", "c", "d", "e"]
ary.sort { |a, b| b <=> a }  #=> ["e", "d", "c", "b", "a"]

reverse()

Bonus tip: Other than using <=> operator, you can rearrange the array in descending order by chaining the reverse method with sort method.

ary.sort.reverse    #=> ["e", "d", "c", "b", "a"]

split() & join()

Last but not least, split and join are the two I use most frequently while doing Codewars challenges.

split()

split divides the string into substrings based on a delimiter, returning an array of these substrings.

Passing a string

If the pattern is a String, then its contents are used as the delimiter when splitting the string.

You can also pass a number as the second argument limit. If the number is positive, for example 4, at most 4 split substrings will be returned. If negative, there is no limit to the number of fields returned.

"mellow yellow".split("ello")   #=> ["m", "w y", "w"]
"1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]

"1,2,,3,4,,".split(',', 1)      #=> ["1,2,,3,4,,"]
"1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
"1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]

Passing nil or a single space

If the pattern is a single space, str is split on whitespace, with leading whitespace and runs of contiguous whitespace characters ignored.

If the pattern is nil, the value of $; is used. If $; is nil (which is the default), str is split on whitespace as if ‘ ’ were specified.

" now's  the time".split        #=> ["now's", "the", "time"]
" now's  the time".split(' ')   #=> ["now's", "the", "time"]

Passing a Regexp

If the pattern is a Regexp, str is divided where the pattern matches. Whenever the pattern matches a zero-length string, str is split into individual characters. If the pattern contains groups, the respective matches will be returned in the array as well.

" now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
"1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
"hello".split(//)               #=> ["h", "e", "l", "l", "o"]
"hello".split(//, 3)            #=> ["h", "e", "llo"]
"hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]

"1:2:3".split(/(:)()()/, 2)     #=> ["1", ":", "", "", "2:3"]

join()

join returns a string created by converting each element of the array to a string, separated by the given separator.

For nested arrays, join is applied recursively:

[ "a", "b", "c" ].join        #=> "abc"
[ "a", "b", "c" ].join("-")   #=> "a-b-c"

[ "a", [1, 2, [:x, :y]], "b" ].join("-")   #=> "a-1-2-x-y-b"

Challenge yourself

After learning all these, you are ready to finish this kata on Codewars. Give it a try!

Did you find this article valuable?

Support Terry Cheng by becoming a sponsor. Any amount is appreciated!