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:
- Stack is an ordered list of similar data type.
- Stack is a LIFO (Last In First Out) structure.
- When creating a new Stack, we have to define the size of the Stack.
Stack Features (2)
More Stack features:
- 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.
- 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.
- Stack is said to be in overflow state when it is completely full.
- 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:
- Stack is an ordered list of similar data type.
- Stack is a FIFO (First In First Out) structure.
- In this lesson, when creating a new Queue, we have to define the size of the Queue.
Queue Features (2)
More Queue features:
- 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.
- 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.
- Queue is said to be in overflow state when it is completely full.
- 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