Advanced Array

in Ruby

Again?!

You must be thinking, "did not we learn about array already?" We did. However, Array is a big class as it has more than 100 public methods. In this lesson we are going to learn some of them, especially the ones you will need but not already covered before.

 

You can take a look at the whole API here.

De-structuring Array (1)

To break down elements of an array, we can use:

a, b = [1, 2]

It also works with multidimensional array.

a, b = [[1, 2], [3, 4, 5]]

It can even work when used inside of a block

[[1, 2], [3, 4, 5]].each { |a, b| puts "#{a} #{b}" }

De-structuring Array (2)

Can you guess the result of these assignments?

a, b = [1, 2, 3]
c, d = [[1, 2], [3, 4, 5], [6, 7]]
e, f, g = [4, 5]

Can you complete this method?

compute([[1, 2], [3, 4]])
# returns [3, 7]

De-structuring Array (3)

a, b = [1, 2, 3]
# the value of a is 1
# the value of b is 2

c, d = [[1, 2], [3, 4, 5], [6, 7]]
# the value of c is [1, 2]
# the value of d is [3, 4, 5]

e, f, g = [4, 5]
# the value of e is 4
# the value of f is 5
# the value of g is nil
def compute(array)
  array.map { |(a, b)| a + b }
end

Splat Operator (1)

We have learned about this before, let's review it again:

head, *tail = [1, 2, 3, 4]
# what is the value of head?
# what is the value of tail?

*head, tail = [5, 6, 7, 8]
# what is the value of head?
# what is the value of tail?

head, *middle, tail = [5, 6, 7, 8]
# what is the value of head?
# what is the value of middle?
# what is the value of tail?

Splat Operator (2)

head, *tail = [1, 2, 3, 4]
# the value of head is 1
# the value of tail is [2, 3, 4]

*head, tail = [5, 6, 7, 8]
# the value of head is [5, 6, 7]
# the value of tail is 8

head, *middle, tail = [5, 6, 7, 8]
# the value of head is 5
# the value of middle is [6, 7]
# the value of tail is 8

Splat Operator (3)

Complete this method:

median(1, 3, 2)
# return the median value of 1, 2, 3 that is 2

median(1, 3, 2, 4)
# return the median value of 1, 2, 3, 4 that is (2 + 3)/2 = 2.5

Splat Operator (4)

Complete this method:

def median(*list)
  mid = list.size/2
  sorted = list.sort

  if sorted.length.odd?
    sorted[mid]
  else
    (sorted[mid-1] + sorted[mid]).to_f / 2
  end
end

Splat Operator (5)

Guess what these operations will return:

a = *(1..10)
# what is the value of a?

b = *"Iqbal"
# what is the value of b?

def compute(a, b)
 a + b
end
# pass [1, 2] to method compute

[[1, 2, 3, 4], [42, 43]].each { |a, *b| puts "#{a} #{b}" }
# what will be printed by the expression above?

Splat Operator (6)

a = *(1..10)
# the value of a is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

b = *"Iqbal"
# the value of b is ["Iqbal"]

def compute(a, b)
 a + b
end
compute(*[1, 2])

[[1, 2, 3, 4], [42, 43]].each { |a, *b| puts "#{a} #{b}" }
# it will print:
# 1 [2, 3, 4]
# 42 [43]

Count (1)

What is the result of these expressions?

[4, 8, 15, 16, 23, 42].count
# what will this return?

[42, 8, 15, 16, 23, 42].count(42)
# what will this return?

["Jacob", "Alexandra", "Mikhail", "Karl", "Dogen", "Jacob"].count("Jacob")
# what will this return?

[4, 8, 15, 16, 23, 42].count { |e| e % 2 == 0 } 
# what will this return?

Count (2)

[4, 8, 15, 16, 23, 42].count
# 6

[42, 8, 15, 16, 23, 42].count(42)
# 2

["Jacob", "Alexandra", "Mikhail", "Karl", "Dogen", "Jacob"].count("Jacob")
# 2

[4, 8, 15, 16, 23, 42].count { |e| e % 2 == 0 } 
# 4

Index (1)

What is the result of these expressions?

[4, 8, 15, 16, 23, 42].index(15)
# what is the return value of expression above?

[4, 8, 15, 16, 23, 42].index { |e| e % 2 == 0 }
# what is the return value of expression above?

Index (2)

[4, 8, 15, 16, 23, 42].index(15)
# 2

[4, 8, 15, 16, 23, 42].index { |e| e % 2 == 0 }
# 0

Flatten (1)

What is the result of these expressions?

[4, 8, 15, 16, 23, 42].flatten
# what is the return value of expression above?

[4, [8], [15], [16, [23, 42]]].flatten
# what is the return value of expression above?

[4, [8], [15], [16, [23, 42]]].flatten(1)
# what is the return value of expression above?

Flatten (2)

[4, 8, 15, 16, 23, 42].flatten
# [4, 8, 15, 16, 23, 42]

[4, [8], [15], [16, [23, 42]]].flatten
# [4, 8, 15, 16, 23, 42]

[4, [8], [15], [16, [23, 42]]].flatten(1)
# [4, 8, 15, 16, [23, 42]]

Compact (1)

What is the result of these expressions?

[nil, 4, nil, 8, 15, 16, nil, 23, 42, nil].compact

Compact (2)

[nil, 4, nil, 8, 15, 16, nil, 23, 42, nil].compact
# [4, 8, 15, 16, 23, 42]

Shift and Unshift (1)

What is the result of these expressions?

a = [4, 8, 15, 16, 23, 42]
b = a.shift
# what is the value of a?
# what is the value of b?

c = [4, 8, 15, 16, 23, 42]
d = a.shift(2)
# what is the value of c?
# what is the value of d?

e = [8, 15, 16, 23, 42].unshift(4)
f = [16, 23, 42].unshift(4, 8, 15)
# what is the value of e?
# what is the value of f?

Shift and Unshift (2)

a = [4, 8, 15, 16, 23, 42]
b = a.shift
# the value of a is [8, 15, 16, 23, 42]
# the value of b is 4

c = [4, 8, 15, 16, 23, 42]
d = c.shift(2)
# the value of c is [15, 16, 23, 42]
# the value of d is [4, 8]

e = [8, 15, 16, 23, 42].unshift(4)
f = [16, 23, 42].unshift(4, 8, 15)
# the value of e is [4, 8, 15, 16, 23, 42]
# the value of f is [4, 8, 15, 16, 23, 42]

Stack & Queue

What is a Stack?

Stack is an abstract data type with a bounded (predefined) capacity. Stack allows adding and removing elements in particular order. Every time an element is added, it goes on the top of the stack. The only element that can be removed from a stack is the element at the top of it.

Stack Features (1)

Here are some basic features of a Stack:

  1. Stack is an ordered list of similar data type.
  2. Stack is a LIFO (Last In First Out) structure.
  3. When creating a new Stack, we have to define the size of the Stack.

Stack Features (2)

More Stack features:

  1. To add an element to a Stack, we use a method (typically) called "push" that place the new element on top of the Stack. When we call "push" method, we need to make sure that Stack is not currently in overflow state.
  2. To remove an element from a Stack, we use a method (typically) called "pop" that remove element at the top of the Stack. When we call "pop" method, we need to make sure that Stack is not currently in underflow state.
  3. Stack is said to be in overflow state when it is completely full.
  4. Stack is said to be underflow state when it is completely empty.

What is a Queue?

Queue is an abstract data type, sometimes implemented with a bounded (predefined) capacity, sometimes not. Queue allows adding and removing elements in particular order. Every time an element is added, it goes to the back part of the queue called "tail" (or sometimes "rear"). The only element that can be removed from a queue is the element at the front part of the queue called "head" (or sometimes just "front").

Queue Features (1)

Here are some basic features of a Queue:

  1. Stack is an ordered list of similar data type.
  2. Stack is a FIFO (First In First Out) structure.
  3. In this lesson, when creating a new Queue, we have to define the size of the Queue.

Queue Features (2)

More Queue features:

  1. To add an element to a Queue, we use a method (typically) called "enqueue" that place the new element on the front of the Queue. When we call "enqueue" method, we need to make sure that Queue is not currently in overflow state.
  2. To remove an element from a Queue, we use a method (typically) called "dequeue" that remove element on the front of the Queue. When we call "dequeue" method, we need to make sure that Queue is not currently in underflow state.
  3. Queue is said to be in overflow state when it is completely full.
  4. Queue is said to be underflow state when it is completely empty.

Queue Features (3)

This is how adding and removing element visualized:

Adding Element

Removing Element

Create Your Own Stack!

require_relative '../stack.rb'

describe "Stack" do
  before :each do
    @s = Stack.new(4)
  end

  it "should be able to be initialized with a size" do
    expect(@s.class.name).to eq("Stack")
  end

  it "should have size" do
    expect(@s.size).to eq(4)
  end

  it "should have elements" do
    expect(@s.elements).to eq([])
  end

  it "should show the size and the elements of the Stack when printed" do
    expect(@s.to_s).to eq("size: 4, elements: []")
  end

  describe "push" do
    context "with normal state" do
      it "should be able to add new element with push method" do
        @s.push(1)
        expect(@s.to_s).to eq("size: 4, elements: [1]")
      end
    end

    context "with overflow state" do
      it "should not be able to add new element with push method" do
        @s.push(1)
        @s.push(2)
        @s.push(3)
        @s.push(4)
        expect(@s.push(5)).to eq("stack overflow, can't add new element")
      end
    end
  end

  describe "pop" do
    context "with normal state" do
      it "should be able to remove an element with pop method" do
        @s.push(1)
        @s.push(2)
        @s.push(3)
        @s.push(4)
        expect(@s.pop).to eq(4)
      end

      it "should be able to remove an element with pop method" do
        @s.push(1)
        @s.push(2)
        @s.push(3)
        @s.push(4)
        @s.pop
        expect(@s.to_s).to eq("size: 4, elements: [1, 2, 3]")
      end
    end

    context "with underflow state" do
      it "should not be able to remove any element with pop method" do
        expect(@s.pop).to eq("stack underflow, can't remove any element")
      end
    end
  end

  describe "look" do
    it "shold be able to look up the top element" do
      @s.push(1)
      @s.push(2)
      @s.push(3)
      @s.push(4)
      expect(@s.look).to eq(4)
    end

    it "shold be able to look up the top element without removing it from the stack" do
      @s.push(1)
      @s.push(2)
      @s.push(3)
      @s.push(4)
      @s.look
      expect(@s.to_s).to eq("size: 4, elements: [1, 2, 3, 4]")
    end
  end
end

Based on this spec, create your own Stack 

Create Your Own Queue!

Create your own spec & implementation of Queue data type.

Advanced Array in Ruby

By qblfrb

Advanced Array in Ruby

  • 252