TheDeveloperBlog.com

Home | Contact Us

C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML

Ruby Iterators: Times, Step Loops

This Ruby article tests and benchmarks iterators. It uses times, upto, downto, step and each.

Iterator. An iterator is a looping construct in Ruby.

It uses method syntax. We optionally use an iteration variable, enclosed in vertical bars.

We invoke times, upto, downto, step and each. These are iterators. With iterators, we simplify loops. This eliminates bugs caused by complex logic.

Times. This can be used with no iteration variable, as in the first example loop. We can add an iteration variable by using the vertical bars around the identifier.

Iteration variable: In the second loop, the variable "i" starts at 0 and is incremented by 1 on each pass through the loop.

Based on:

Ruby 2

Ruby program that uses times

# Use a times-loop.
4.times do
    puts "a"
end

# Use a times iterator with an iteration variable.
5.times do |i|
    puts i
end

Output

a
a
a
a
0
1
2
3
4

Upto. This starts at the first number and proceeds through the argument. Here we use iteration variables "x" and "y." We also nest an iterator loop.

And: The nested loop uses upto with a variable start and end. An expression, "x + 2," is provided.

Output: The program loops over the indexes 3, 4 and 5. And at each index, it loops over the next two highest numbers.

Ruby program that iterates with upto

# Go up from 3 to 5.
3.upto(5) do |x|

    # Go up from x to x + 2.
    x.upto(x + 2) do |y|
	# Display variable.
	print y, " "
    end

    # End the line.
    print "\n"
end

Output

3 4 5
4 5 6
5 6 7

Upto, short syntax. Iterators can be used with a short block syntax form. We use curly brackets and omit the do keyword. This is shorter to type, but harder to add statements to later.

Ruby program that uses upto, short syntax

# Use block syntax.
# ... The do keyword is not required here.
# ... Use format string with puts to write the numbers.
0.upto(3) {|x| puts("Number: %x" % x)}

Output

Number: 0
Number: 1
Number: 2
Number: 3

Downto. This decrements a number. It reduces the number by 1 after each pass through the iterator body. If the argument is not lower, the iterator body is not executed.

Tip: The downto iterator is best used for simple loops. The step iterator allows complex or unusual iteration steps—even decrements.

However: As a general rule, using the simplest syntax form necessary for any operation is ideal. If downto is effective, use it.

Ruby program that uses downto, decrements

# Decrement from 5 to 3.
5.downto(3) do |j|

    # Display the index.
    puts j
end

Output

5
4
3

Step. This allows us to specify all parts of a loop. We indicate the starting index, the ending index, and the step—the change after each iteration.

First argument: This is the ending index. In the first loop, we end at the index 10. In the second, we end at 6.

Second argument: This is the step. The iteration variable is changed by this amount—positive or negative—after each pass.

Ruby program that uses step

# Increment from 0 to 10, by 2 each time.
# ... Name the iteration variable "v".
0.step(10, 2) do |v|
    puts v
end

# Decrement from 12 to 6, by -2 each time.
# ... Name the iteration variable "iter".
12.step(6, -2) do |iter|
    puts iter
end

Output

0
2
4
6
8
10
12
10
8
6

Step notes. Should we always use step? The step method can duplicate the other loops shown. It is powerful, but may be more complex than upto or downto.

Thus: A primary reason why we should not always use step is that it introduces further complexity. Using downto, upto or times is simpler.

Tip: Code that is simpler to read is less likely to cause bugs. It can be checked and understood faster.

Each. This is available on arrays. It accesses each array element. With the iteration variable, we can then test and use the element. The index number remains unavailable.

Each

String: With a string iterator, we have several ways to loop over the contents of strings.

Each_char

Yield. Here we can implement our own iterators. This code introduces an addthree() method, which yields a sequence of numbers starting at zero, incrementing by 3 each time.

Tip: With this style of code, we do not need to manage indexes or increment a variable to loop over a custom sequence or range.

Tip 2: With a custom iterator, we can separate the complexity of a loop into a single, reusable method.

Ruby program that implements iterator, uses yield

def addthree(max)
    # Return a sequence incremented by three up to the max.
    i = 0
    while i <= max
	yield i
	i += 3
    end
end

# Display sequence up to 20.
addthree(20) do |n|
    puts n
end

Output

0
3
6
9
12
15
18

Performance. Are iterators slower than for-loops? In this benchmark, I tested the times iterator against an equivalent for-loop. I found that the iterator was slightly faster.

And: The results were repeatable. The ordering of the tests did not change my results. The times iterator consistently was somewhat faster.

So: When composing Ruby programs, I would not shy away from using iterators. They may have better performance than loops.

Ruby that benchmarks iterator, for-loop

count = 750000
n1 = Time.now.usec

# Version 1: use times iterator.
v = 0
count.times do
    v += 1
end
puts v

n2 = Time.now.usec

# Version 2: use for-loop.
v = 0
for i in 0..count-1
    v += 1
end
puts v

n3 = Time.now.usec

# Compute millisecond timings.
puts ((n2 - n1) / 1000)
puts ((n3 - n2) / 1000)

Output

750000
750000
61    [Time in ms: times() iterator]
64    [Time in ms: for-loop]

Simplify. Iterators help make loops simpler. With them, we eliminate index variables when possible. This reduces code complexity, which in turn prevents bugs.

Some favorites. With upto, downto and times we can iterate. Step is more powerful. Step might seem tempting to always use, but code is more readable with upto and its sad friend downto.


Related Links

Adjectives Ado Ai Android Angular Antonyms Apache Articles Asp Autocad Automata Aws Azure Basic Binary Bitcoin Blockchain C Cassandra Change Coa Computer Control Cpp Create Creating C-Sharp Cyber Daa Data Dbms Deletion Devops Difference Discrete Es6 Ethical Examples Features Firebase Flutter Fs Git Go Hbase History Hive Hiveql How Html Idioms Insertion Installing Ios Java Joomla Js Kafka Kali Laravel Logical Machine Matlab Matrix Mongodb Mysql One Opencv Oracle Ordering Os Pandas Php Pig Pl Postgresql Powershell Prepositions Program Python React Ruby Scala Selecting Selenium Sentence Seo Sharepoint Software Spellings Spotting Spring Sql Sqlite Sqoop Svn Swift Synonyms Talend Testng Types Uml Unity Vbnet Verbal Webdriver What Wpf