Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Iterator is a term used in object-oriented programming. Iteration is the repetition of a single action, similar to a loop. The loop method is the most basic iterator. They return all the components of a collection one by one. Arrays and hashes are examples of collections.
Although while, until, and for loops are fundamental to the Ruby programming language, iterators are arguably more commonly used to create loops.
For example:
3.times { puts "thank you!"} # Express gratitude three times
data.each {|x| puts x } # Print each element x of data
[1,2,3].map {|x| x*x } # Compute squares of array elements
factorial = 1 # Compute the factorial of n
2.upto(n) {|x| factorial *= x }
You can also try this code with Online Ruby Compiler
An enumerator is an Enumerable object that enumerates another item. To utilise enumerators with Ruby 1.8, you must use the keyword 'enumerator'. Enumerators are built-in in Ruby 1.9. Therefore no need is required.
Enumerators are members of the Enumerable::Enumerator class. Although this class may be immediately constructed using new, this is not how most enumerators are built. Instead, use to enum or its synonym enum for, which are Object methods. With no parameters, to enum provides an enumerator whose each method calls the target object's each method.
We can send the arguments to the enum. However, the enum for synonym seems more logical in this instance. The first parameter must be a symbol representing an iterator method. The designated method of the original object will be invoked by each method of the resultant Enumerator.
Any leftover enum for arguments will be given to the selected method. The String class in Ruby 1.9 is not Enumerable but has three iterator methods: char, byte, and line. Assume we wish to utilise an Enumerable function like the map based on each char iterator. We accomplish this by developing an enumerator:
Enumerators have been discussed in terms of their utility as Enumerable proxy objects. Enumerators are another essential purpose in Ruby 1.9: external iterators. You may use an enumerator to loop through the items of a collection by using the next function repeatedly. This function throws a StopIteration exception when there are no more elements.
For example:
iterator = 9.downto(1) # An enumerator as external iterator
begin
print iterator.next while true
rescue StopIteration
puts "...blastoff!" # An expected, nonexceptional condition
end
You can also try this code with Online Ruby Compiler
External iterators in ruby are easy to use: simply use next each time you wish to add another element. When no more elements are found, the “next” throws a StopIteration exception. This may appear unusual—an exception is raised for a predicted termination condition rather than an unexpected and extraordinary event. In this external iteration mechanism, Ruby follows Python. By treating loop termination as an exception, you simplify your looping logic; there is no need to verify the next return value for a particular end-of-iteration value, and there is no need to execute any form of next function.
To make looping with external iterators in ruby easier, the “Kernel.loop” function provides an implicit rescue clause (in Ruby 1.9) and quits when StopIteration is invoked. As a result, the earlier countdown code might be more readily expressed as follows:
iterator = 9.downto(1)
loop do # Loop until StopIteration is raised
print iterator.next # Print the next item
end
puts "...blastoff!"
You can also try this code with Online Ruby Compiler
The example below shows the parallel iteration with external iterators.
def sequence(*enumerable, &block)
enumerable.each do |enumerable|
enumerable.each(&block)
end
end
# Iterate the provided collections, interleaving their elements.
# This cannot be completed efficiently without the need of external
# iterators.
def interleave(*enumerable)
# Convert enumerable collections to an array of enumerator.
enumerator = enumerable.map {|e| e.to_enum }
# Loop until we don't have any more enumerator.
until enumerator.empty?
begin
e = enumerator.shift
yield e.next
rescue StopIteration
else # If no exception occurred
enumerator << e
end
end
end
# Iterate the provided collections, yielding tuples of values,
# one value from each of the collections. See also Enumerable.zip.
def bundle(*enumerable)
enumerator = enumerable.map {|e| e.to_enum }
loop { yield enumerator.map {|e| e.next} }
end
# Examples
a,b,c = [4,5,6], 7..9, 'a'..'e'
sequence(a,b,c) {|x| print x}
print "\n"
interleave(a,b,c) {|x| print x}
print "\n"
bundle(a,b,c) {|x| print x}
You can also try this code with Online Ruby Compiler
A fundamental difficulty is determining who controls the iteration: the iterator or the client who utilises it. The iterator is referred to as an external iterator when the client controls the iteration. When the iterator controls the iteration, the iterator is referred to as an internal iterator. Clients who utilise an external iterator must progress the traverse and explicitly request the next element from the iterator. In contrast, the client assigns an operation to an internal iterator, and the iterator applies that action to each element.
Internal iterators are less adaptable than external iterators in ruby. It's simple to compare two collections for equality using an external iterator, but it's nearly complicated with internal iterators. On the other hand, internal iterators are simpler to use since they specify the iteration logic for us.
Internal iterators in Ruby are iterator methods like each; they control iteration and"push" values to the method call's related code block. Enumerators feature an "each" method for internal iteration. Still, they also operate as external iterators in Ruby 1.9 and later—client code may use next to successively "pull" data from an enumerator.
Frequently Asked Questions
What exactly is the distinction between internal and external iterators in ruby?
Iterators are classified into two types: external iterators in ruby and internal iterators in ruby. An external iterator is active, whereas an internal iterator is inactive. When the iteration is controlled by the client (i.e. the programmer), the iterator is referred to as an external iterator. It is referred to as an internal iterator when the iterator controls it.
In Ruby, how do we use iterator?
Ruby's object-oriented idea is "iterators." In a nutshell, Iterators are the techniques supported by collections (Arrays, Hashes etc.). Collections are objects that hold a group of data members. Ruby iterators return each element of a collection one by one.
What is an external iterator?
This Iterator is sometimes referred to as an active iterator or an explicit iterator. The programmer controls the iteration of components in this form of the iterator. The programmer determines when and how the next iteration element is invoked.
What is an enumerator in Ruby?
Enumerator, in particular, is a class that supports both internal and external iterators in ruby. Internal iteration refers to iteration managed by the class in question, whereas external iteration refers to iteration controlled by the environment or the client.
Internally, how does iterator work?
For most basic java collections, the iterator just stores a reference to where the iterator is in the collection. The iterator is advanced by using. next(). It does not duplicate the items and just returns the next entry in the collection.
In this article, we have extensively discussed the external iterators in ruby and the difference between internal and external iterators in ruby.
After reading about the external iterators in ruby and the difference between internal and external iterators in ruby, are you not feeling excited to read/explore more articles on the topic of DSA? Don't worry; Coding Ninjas has you covered. To learn, see Try Ruby, the History of Ruby and Constants in Ruby.