Ruby provides a multitude of methods and structures for iterating or looping through arrays and collections. The most commonly used methods are the basic for and each loops. However there exists other convenience (or code bloat) methods on both arrays and integers to also perform iteration.

The basic FOR loop

The for loop in Ruby functions allows you to iterator through each item in an expression. Where the expression can be an array, collection, or a range.

for i in myArray
    puts "Value of Array index is: #{i}"
end
 
for j in 0..10
    puts j
end

In the second example we are using a Range. In Ruby we can define a range of numbers inclusively by use of the number . . number syntax. The above example will iterate starting at 0 and end at 10.

The Each Statement

The each iterator is similar to the for statement as it loops through the array or hash for every element setting the current element to the defined variable. The one important element to remember is that for hash objects you will need to specify two variables to hold both the key and value.

myArray.each do |var|
    puts i
end
 
myHash.each do |varKey, varValue|
    puts "key: #{varKey} | value: #{varValue}"
end

In addition to the main each statement Ruby has also defined additional methods to iterate over the indexes of a collection each_index and to also return both the element and its index each_with_index. However it is important to remember that the each_with_index function returns the element first then the index.

myArray.each_with_index do |value, index|
    puts "index: #{index} | value: #{value}"
end

Integer iteration with TIMES, UPTO, and DOWNTO

For those that find the for statement cumbersome Ruby has found the need to define the times, upto and downto methods for iterating.

4.times do
    puts "Hello"
end

The times method is used to execute a block of code for the specified number of times. If needed you could also get the current loop index that will start at 0 and go to times – 1.

10.times do |i|
    puts i
end

If you don’t want to iterate starting at 0 for a specific number of times but instead want to iterate over a range then you can use the upto and downto methods. These methods iterate from the integer’s value to the specified value.

1.upto(5) do |i|
    puts i 
end
 
15.downto(10) do |i|
    puts i
end

It is important to remember that the downto and upto method are inclusive so in the example 6 iterations of the code block will occur. Personally I don’t see the reason for these methods, all of the logic that you can perform from it can be created using a simple for loop and why would you need both an upto and downto method why not simply have a to method that could do either depending on if the specified number is larger or smaller. Seriously if you are going to add convenience methods for no other reason then to do so then atleast go all the way.

The Collect and Map functions

While we are on the topic of iteration it is important to touch on the collect and map functions. These functions are used to return a collection after performing the specified code block on each element of the existing collection. As you can tell from the name these functions are most useful in mapping a collection into a new collection with different values.

myArray = ['a','b','c','d']             #=> ["a", "b", "c", "d",]
newArray = myArray.map {|item| item.upcase}      #=> ["A", "B", "C", "D"]

Ruby definitely defines some different methods for performing collection iteration, however no new functionality is presented. Instead we see once again the existence of additional code and functions that add bloat and ambiguity to the core of Ruby. Nearing the end of my self-inflicted crash course, and to date I must say I am not impressed.

, , , , , , , , , , , , ,

JavaServer Pages Standard Tag Library or JSTL for short is a library that contains a set of core functionality including iterations and conditionals.  The tag I find myself most often using is the forEach tag to output a collection of data in a consistent format. By use of the optional status object and the if tag you can even put logic in that executes only if the item being iterated is first or last in the collection.

Getting Started

To utilize JSTL you first need to download the appropriate jar file and import it into you project in the web library. Once in your project you need to import the tag definition into your page using the following code.

<%@ taglib prefix="c" uri="http://java/sun.com/jsp/jstl/core %>

Basic ForEach Tag Usage

Once the tag library is imported we can use it by specifying 2 attributes var and items. VAR is used to denote the reference that the current item being iterated in the collection can be accessed by, while ITEMS specifies the collection to be iterated upon. Lets assume me have a collection of User objects that each have a firstName, lastName, and email property.  We could iterate over them with the following code.

<c:forEach var="user" items="${users}">
</c:forEach>

The above code is functional but doesn’t output any data lets expand upon it by having it export rows of a table with the three properties each in their own cell.

<table>
  <tr>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Email</th>
  </tr>
  <c:forEach var="user" items="${users}">
    <tr>
      <td>${user.firstName}</td>
      <td>${user.lastName}</td>
      <td>${user.email}</td></tr>
  </c:forEach>
</table>

Advanced Usage: The varStatus Attribute

In addition to iteration over the collection the ForEach tag provides a status object that can be used to obtain information about where you are in the collection.

<c:forEach var "user" items="${users}" varStatus="status">
</c:forEach>
  • first and last property
    The status object contain a first and last property that returns a boolean set to true or false if the current item being iterated over is the first or last object in the collection. You can utilize the if tag to have code execute if it is one of these conditions.

    <c:if test="${status.last}">
      // code
    </c:if>
  • index property
    The index property gives you the current index of the object within the collection this value can be used to output different classes on odd and even rows for example, in addition to other uses.

    <table>
      <tr>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Email</th>
      </tr>
      <c:forEach var="user" items="${users}" varStatus="status">
        <tr class="${status.index % 2 == 0 ? 'even' : 'odd'}">
          <td>${user.firstName}</td>
          <td>${user.lastName}</td>
          <td>${user.email}</td>
        </tr>
      </c:forEach>
    </table>

Resources

, ,