Array in Ruby

Definition

An Array is ordered, integer-indexed collections of any object.

Creating an Array (1)

arr = []
# or
arr = Array.new

To create an empty array, simply use:

arr = [1, 2, 3, 4, 5]
arr = ["a", "b", "c", "d", "e"]

We can also create an array with a set of values:

arr = %w(This is another way to make array of strings)
# result: ["This", "is", "another", "way", "to", "make", "array", "of", "strings"]

We can also create an array of strings like this:

Creating an Array (2)

arr = [1, "a", 2, "b", 3, "c"]

An array can contain different data types.

arr = [1, 2, 3, 4, 5]
arr << 6 # result: [1, 2, 3, 4, 5, 6]

To add an element to an array, we can use:

# Another way to create an array
arr = Array.new(3, 'abc')       # ["abc", "abc", "abc"]
arr[0].upcase!
arr                             # ["ABC", "ABC", "ABC"]
arr[1] = 'xyz'
arr                             # ["ABC", "xyz", "ABC"]

# This time using block, we'll discuss about block later this week
arr = Array.new(3) { 'abc' }    # ["abc", "abc", "abc"]
arr[0].upcase!
arr                             # ["ABC", "abc", "abc"]
arr[1] = 'xyz'
arr                             # ["ABC", "xyz", "abc"]

# This can be used to do many things, for instance: creating a multidimensional array
i = 1
Array.new(4) { Array.new(4) { i += 1 } }
# [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

Accessing an Element of an Array (1)

# Guess what is the result of this expression:
[1, 2, 3, 4, 5][1]
[1, 2, 3, 4, 5].at[3]

To access an element in an array, we use its index.

# Guess what is the result of this expression:
[1, 2, 3, 4, 5][-2]
# Hint:
# With reverse index lookup, 
# the last element of an array has an index value of -1

We can also use negative numbers as index. This is called reverse index lookup.

Accessing an Element of an Array (2)

[1, 2, 3, 4, 5] # return 3
[1, 2, 3, 4, 5] # return 3 using reverse index lookup

# Without using index, 
# Guess which methods to solve these:
[1, 2, 3, 4, 5].your_method_here # return the first element of this array
[1, 2, 3, 4, 5].your_method_here # return the last element of this array

Accessing an Element of an Array (3)

[1, 2, 3, 4, 5][2]    # return 3
[1, 2, 3, 4, 5][-3]   # return 3 using reverse index lookup

# Without using index, 
# Guess which methods to solve these:
[1, 2, 3, 4, 5].first # return the first element of this array
[1, 2, 3, 4, 5].last  # return the last element of this array

Slicing Elements of an Array (1)

arr = ["a", "b", "c", "d"]

arr[0, 1]
# result: ["a"]

# Can you guess the results of these expressions?
arr[0, 2]
arr[2, 2]
arr[2, 20]
arr[4, 0]
arr[4, 100]
arr[5, 0]

Slicing Elements of an Array (2)

arr = ["a", "b", "c", "d"]

arr[0, 2]
# ["a", "b"]

arr[2, 2]
# ["c", "d"]

arr[2, 20]
# ["c", "d"]

arr[4, 0]
# []

arr[4, 100]
# []

arr[5, 0]
# nil

# Expression arr[4, 100] returns [], but arr[5, 0] returns nil. Why?

Slicing Elements of an Array (3)

#  -4  -3  -2  -1    << reverse index lookup
#   0   1   2   3    << normal index
# +---+---+---+---+
# | a | b | c | d |
# +---+---+---+---+
# 0   1   2   3   4  << numbering for two-argument indexing or start of range

Slicing Elements of an Array with Range

# Try this:
(1..5)
(1..5).class
(1...5)

# What will this return?
[1, 2, 3, 4, 5] == (1..5)
[1, 2, 3, 4, 5] == (1..5).to_a
[1, 2, 3, 4, 5] == (1...5).to_a

In Ruby, there is a class called Range. 

# Guess what is the result of this expression:
["a", "b", "c", "d"][0..2]
["a", "b", "c", "d"][0...2]
["a", "b", "c", "d"][2..-1]

We can slice an array using range.

Array Assignment (1)

a = [ 1, 3, 5, 7, 9 ]
a[1] = 'bat'         
a[-3] = 'cat'        
a[3] = [ 9, 8 ]      
a[6] = 99            

Array Assignment (2)

a = [ 1, 3, 5, 7, 9 ]     #=> [1, 3, 5, 7, 9]
a[1] = 'bat'              #=> [1, "bat", 5, 7, 9]
a[-3] = 'cat'             #=> [1, "bat", "cat", 7, 9]
a[3] = [ 9, 8 ]           #=> [1, "bat", "cat", [9, 8], 9]
a[6] = 99                 #=> [1, "bat", "cat", [9, 8], 9, nil, 99]

Array Assignment (3)

a = [ 1, 3, 5, 7, 9 ]
a[2, 2] = 'cat'      
a[2, 0] = 'dog'      
a[1, 1] = [ 9, 8, 7 ]
a[0..3] = []         
a[5..6] = 99, 98     

Array Assignment (4)

a = [ 1, 3, 5, 7, 9 ]     #=> [1, 3, 5, 7, 9]
a[2, 2] = 'cat'           #=> [1, 3, "cat", 9]
a[2, 0] = 'dog'           #=> [1, 3, "dog", "cat", 9]
a[1, 1] = [ 9, 8, 7 ]     #=> [1, 9, 8, 7, "dog", "cat", 9]
a[0..3] = []              #=> ["dog", "cat", 9]
a[5..6] = 99, 98          #=> ["dog", "cat", 9, nil, nil, 99, 98]

Transforming Arrays (1)

[1, 2, 3, 4, 5].map { |i| i + 1 }
# Will generate a new array: [2, 3, 4, 5, 6]

We can transform the contents of an array according to  a specified set of rules using the "map" method.

# Transform this array, multiple each element by 3
[1, 2, 3, 4, 5]

The curly braces and everything inside them is called a block. We'll come back to that later.

Transforming Arrays (2)

[1, 2, 3, 4, 5].collect { |i| i + 1 }
# Will generate a new array: [2, 3, 4, 5, 6]

We can also use the method "collect" which is an alias to the method "map". The two methods work interchangeably.

Transforming Arrays (3)

[1, 2, 3, 4, 5].collect { |i| i + 1 }
# Will generate a new array: [2, 3, 4, 5, 6]

We can also use the method "collect" which is an alias to the method "map". The two methods work interchangeably.

Filtering Elements of an Array

# Select only even numbers
[1,2,3,4,5,6].select { |number| number.even? }

# Select regions that has 6 or more characters
regions = ["Senen", "Menteng", "Gambir", "Cikini", "Pluit"]
regions.select { |region| region.size >= 6 }

We can filter elements of an array using the method "select".

Deleting Elements of an Array (1)

# Guess which method to use 

# 1. To delete element 4 from this array
arr = [1, 2, 3, 4, 5, 6]
arr.your_method_here

# 2. To delete the fourth element from this array
arr = [1, 2, 3, 4, 5, 6]
arr.your_method_here

# 3. To delete every even number from this array
arr = [1, 2, 3, 4, 5, 6]
arr.your_method_here

Deleting Elements of an Array (2)

# 1. To delete element 4 from this array
arr = [1, 2, 3, 4, 5, 6]
arr.delete(4)

# 2. To delete the fourth element from this array
arr = [1, 2, 3, 4, 5, 6]
arr.delete_at(3)

# 3. To delete all odd numbers from this array
arr = [1, 2, 3, 4, 5, 6]
arr.delete_if { |number| number.odd? }

Iterating Elements of an Array (1)

arr = ["Giovanni", "Iqbal", "Raymond", "Tara"]
for i in 0..3 do
  puts "My name is #{arr[i]}"
end

We have learned about loop. To iterate elements in Ruby, we can use loop. In other programming languages, we may do something like this:

Iterating Elements of an Array (2)

arr = ["Giovanni", "Iqbal", "Raymond", "Tara"]
for i in arr do
  puts "My name is #{i}"
end

In Ruby, we can do it in better ways. For instance:

Iterating Elements of an Array (3)

arr = ["Giovanni", "Iqbal", "Raymond", "Tara"]
arr.each do |name|
  puts "My name is #{name}"
end

Even better, we can do it this way:

Exercises (1)

insert_dash(454793) # will return: '4547-9-3'
insert_dash(123456) # will return: '123456'
insert_dash(1003567) # will return: '1003-567'
insert_dash(24680) # will return: '24680'
insert_dash(13579) # will return: '1-3-5-7-9'

1. Insert Dash

Create a method called insert_dash. When given a number, this method will return a string containing the number with dash added between occurrences of two odd number consecutively.

Exercises (2)

high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6") 
# return "542 -214"

high_and_low("1 -1")    # return "1 -1"
high_and_low("1 1")     # return "1 1"
high_and_low("-1 -1")   # return "-1 -1"
high_and_low("1 -1 0")  # return "1 -1"
high_and_low("1 1 0")   # return "1 0"
high_and_low("-1 -1 0") # return "0 -1"
high_and_low("42")      # return "42 42"

2. High and Low

Create a method called high_and_low. When given a string consisting a sequence of numbers, this method will return a string containing the highest and the lowest numbers in the sequence.

Exercises (3)

find_longest([1, 10, 100])     # return 100
find_longest([9000, 8, 800])   # return 9000
find_longest([8, 900, 500])    # return 900
find_longest([3, 40000, 100])  # 40000
find_longest([1, 200, 100000]) # return 100000)

3. Longest Digit

Create a method called find_longest. When given an array containing positive numbers, it will return the element with the longest digit. If there are two or more elements with the longest digit, it will return the first element with the longest digit.

Exercises (4)

a1 = ["arp", "live", "strong"]
a2 = ["lively", "alive", "harp", "sharp", "armstrong"]

in_array(a1, a2) 
# will return: ["arp", "live", "strong"]

a1 = ["tarp", "mice", "bull"]
in_array(a1, a2)
# will return: []

4. In Array

Create a method called in_array. It receives two parameters "array1" and "array2". It will return an array containing unique elements of array1 that is a subset of elements in array2, arranged alphabetically.

Exercises (5)

deep_count([]) # will return 0
deep_count([1, 2, 3]) # will return 3

deep_count(["x", "y", ["z"]]) 
# will return 3 elements ("x", "y", ["z"]) in main array 
# plus 1 element ("z") in sub array 
# total = 4 elements

deep_count([1, 2, [3, 4, [5]]])
# total = 7 elements

deep_count([[[[[[[[[]]]]]]]]])
# total = 8 elements

5. Deep Count

Create a method called deep_count that will return the number of elements in an array, including the number of elements of its sub arrays.

Solutions (1)

def insert_dash(num)
  i = 0
  dashed_number = ""
  num.to_s.chars.each do |char|
    if char.to_i.odd? && dashed_number[i-1].to_i.odd?
      i += 1
      dashed_number += "-" 
    end
    dashed_number += char
    i += 1
  end
  
  dashed_number
end

1. Insert Dash - Basic Solution

Solutions (2)

def insert_dash(num)
  num.to_s.gsub(/(?<=[13579])([13579])/, '-\1')
end

1. Insert Dash - Advanced Solution

Solutions (3)

def high_and_low(numbers)
  arr = numbers.split(" ").map { |e| e.to_i }
  "#{arr.max} #{arr.min}"
end

2. High and Low - Basic Solution

Solutions (4)

def high_and_low(numbers)
  numbers.split(" ").map { |e| e.to_i }.minmax.reverse.join(' ')
end

2. High and Low - Advanced Solution

Solutions (5)

def find_longest(arr)
  longest = nil
  max_digit = 0
  arr.each do |a|
    if a.to_s.size > max_digit
      max_digit = a.to_s.size
      longest = a
    end
  end
  longest
end

3. Longest Digit - Basic Solution

Solutions (6)

def find_longest(arr)
  arr.max_by { |num| num.to_s.size }
end

3. Longest Digit - Advanced Solution

max_by() # public
# Returns the object in enum that gives the maximum value from the given block.
# If no block is given, an enumerator is returned instead.
# source: https://apidock.com/ruby/Enumerable/max_by

Reference

Solutions (7)

def in_array(array1, array2)
  subset_array = []
  array1.each do |a1|
    array2.each do |a2|
      subset_array << a1 if a2[a1] && !subset_array.include?(a1)
    end
  end
  
  subset_array.sort
end

4. In Array - Basic Solution

Solutions (8)

def in_array(array1, array2)
  array1.select{|s| array2.any?{|w| w.include?(s) } }.sort
end

4. In Array - Advanced Solution

Solutions (9)

def deep_count(a)
  count = 0
  if !a.empty?
    a.each do |e|
      count += 1
      if e.is_a?(Array)
        count += deep_count(e)
      end
    end
  end
  count
end

10. Deep Count - Basic Solution

Solutions (10)

def deep_count(a)
  a.reduce(a.size) {
    |size, element| size + (element.is_a?(Array) ? deep_count(element) : 0) 
  }
end

# reduce(p1 = v1, p2 = v2) public
# Combines all elements of enum by applying a binary operation,
# specified by a block or a symbol that names a method or operator.

# If you specify a block, then for each element in enum 
# the block is passed an accumulator value (memo) and the element.
# If you specify a symbol instead, then each element in the collection 
# will be passed to the named method of memo. 
# In either case, the result becomes the new value for memo.
# At the end of the iteration, 
# the final value of memo is the return value for the method.

# If you do not explicitly specify an initial value for memo, 
# then uses the first element of collection is used as the initial value of memo.

# source: https://apidock.com/ruby/Enumerable/reduce

5. Deep Count - Advanced Solution

Array in Ruby - with Solution

By qblfrb

Array in Ruby - with Solution

  • 213