Collections, Blocks, and Iterators
Download
Report
Transcript Collections, Blocks, and Iterators
CS 480/680 – Comparative Languages
Ruby Containers, Blocks, and
Iterators
Array Review
Ruby arrays are collections of object references
Arrays must be expressly created, but are
dynamically sized
• Undefined elements have the value nil, which also
equates to false
Arrays are indexed with []
• First element is 0
• Negative numbers start at the end
array[-1] is the last element
See array.rb
Blocks & Iterators
2
Useful array operators
& – array intersection
• [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]
» [1, 3]
* – repetition
• [ 1, 2, 3 ] * 2
» [1, 2, 3, 1, 2, 3]
+ – concatenation
• [ 1, 2, 3 ] + [ 3, 4, 5 ]
» [1, 2, 3, 3, 4, 5]
| – union
• [ 1, 2, 3 ] | [ 3, 4, 5 ]
» [1, 2, 3, 4, 5]
delete
• a = [ 1, 2, 3, 3, 5 ]
a.delete(3)
a » [1, 2, 3, 3, 4, 5]
Blocks & Iterators
3
More useful array operators
empty? – returns true if empty, else false
index(c) – returns index of first element == c
join – concatenates array elements into a string
•
•
[ 1, 2, 3].join
» “123”
[ 1, 2, 3].join(“-”)
» “1-2-3”
length – returns # elements
nitems – returns # non-nil elements
reverse, sort – return a reversed/sorted array
Many others in the Ruby book: Built-in
Classes and Methods/Array
Blocks & Iterators
4
Arrays as stacks and queues
a.push(item) – add item to the end of an a
a.pop – returns the last item of a, or nil if empty
a.shift – returns and removes the first element
of a, shifts every other element down by one
a.unshift(item) – prepends item to the start of a,
moving all elements up one index
Stack – push & pop
Queue – push & shift
Blocks & Iterators
5
Arrays as method parameters
a = [1, 2, 3, 4, 5, ‘a’, ‘b’, ‘c’]
someMethod(a) – passes one array argument
someMethod(*a) – passes 8 parameters, the
elements of the array (expands the array)
def someMethod(*a) … collect all the
parameters passed into array a
Blocks & Iterators
6
Hashes
While the index to an array is an integer, the
index to a hash can be any type
• Some care must be taken here… more on that later
A hash is essentially a list of key value pairs
No implicit ordering
• Can’t do stacks/queues
Most common data structure in Ruby!
• h = { 'dog' => 'canine', 'cat' => 'feline', \
'donkey' => 'asinine' }
• h.length » 3
; h['dog'] » "canine"
Blocks & Iterators
7
Implementation Details
See jukebox.rb
Note:
• Functions that behave differently with different
types of arguments (similar to C++ overloading, but
implemented very differently)
• Use of blocks and iterators: @songs.find{}
• Array as a stack/queue
Blocks & Iterators
8
Ruby Iterators
An iterator in Ruby is a method that gets
passed a code block, and it runs that code block
on every element in a collection, and returns a
specific result
• Code blocks are enclosed in {}
• Parameters to code blocks are listed between |’s
Blocks & Iterators
9
Iterators for arrays
See iterators.rb
a.each – calls block once for each item in a,
passing the item as a parameter
a.each_index – passes the index, not the item
b = a.collect – calls block once for each item in
a, block’s return values are collected in b
a.sort – optional block
a.delete_if – block should return true or false
a.find – return first element of array for which
block returns true
Blocks & Iterators
10
Writing your own iterators
An iterator is simply a method that calls a block
of code, possibly passing parameters
Example: Given a chunk of code, execute it
three times.
Solution:
• C/C++ maybe possible with function pointers
• Ruby: def threeTimes
Blocks & Iterators
Call any block
yield
passed to this
yield
method.
yield
end
threeTimes { puts "Hello" }
11
Iterator Parameters
Call any block of code, passing it each even
number up to n:
def evenUpTo(max)
i = 2
while i <= max
yield i
i *= 2
end
end
evenUpTo(1000) { |f| print f, " " }
Blocks & Iterators
12
Another example
The find() method for class SongList might be
implemented like this:
class SongList
def find
for i in 0...songs.size
title = songs[i].name
return title if yield(title)
end
return nil
end
end
# Find first song title starting with ‘A’:
myList.find {|title| title[0,1] == ‘A’ }
Blocks & Iterators
13
Last iterator example
Iterators are very useful in file I/O:
f = File.open("testfile")
f.each {|line|
print line
}
f.close
Blocks & Iterators
14
Blocks
Ruby style programming uses blocks and
iterators as often as possible
Blocks cannot use an explicit return()
statement, the last value calculated in the block
is the return value
Blocks can be specified between {}’s or
between a do and end pair
Blocks & Iterators
15
Blocks for transactions
If File.open is passed a block, it will…
• Open the file
• Call the block, passing it the opened file object
• Close the file when the block exits
File.open("testfile") do |f|
f.each {|line|
print line
end
Blocks & Iterators
16
Exercises
Write a simple RPN calculator, using an array as a
stack, and only dealing with operators +, -, *, and /
Write a subroutine (method) that takes a variable
number of arguments and prints them all to standard
out
Write a program that uses array.collect to look at an
array, and copy every element divisible by three into a
new array
Write an iterator for your student class that returns an
array of each test score that passes a test – the test is
the block for the iterator and should return true or
false. Call the iterator collect_exams_if
Blocks & Iterators
17