Ruby-on-Rails
  Home arrow Ruby-on-Rails arrow Page 4 - Iterators in Ruby
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
RUBY-ON-RAILS

Iterators in Ruby
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 1
    2007-03-08

    Table of Contents:
  • Iterators in Ruby
  • 7.5 Writing an Iterator Over a Data Structure
  • 7.6 Changing the Way an Object Iterates
  • 7.7 Writing Block Methods That Classify or Collect

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Iterators in Ruby - 7.7 Writing Block Methods That Classify or Collect


    (Page 4 of 4 )

    Problem

    The basic block methods that come with the Ruby standard library aren’t enough for you. You want to define your own method that classifies the elements in an enumeration (like Enumerable#detect andEnumerable#find_all), or that does a transformation on each element in an enumeration (likeEnumerable#collect).

    Solution

    You can usually use inject to write a method that searches or classifies an enumeration of objects. With injectyou can write your own versions of methods such asdetectandfind_all:

      module Enumerable
       
    def find_no_more_than(limit)
         
    inject([]) do |a,e|
           
    a << e if yield e
           
    return a if a.size >= limit
           
    a
         
    end
        end
      end

    This code finds at most three of the even numbers in a list:

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      a.find_no_more_than(3) { |x| x % 2 == 0 } # => [2, 4, 6]

    If you find yourself needing to write a method likecollect, it’s probably because, for your purposes,collectitself yields elements in the wrong order. You can’t useinject, because that yields elements in the same order ascollect.

    You need to find or write an iterator that yields elements in the order you want. Once you’ve done that, you have two options: you can write acollect equivalent on top of the iterator method, or you can use the iterator method to build anEnumerable object, and call itscollectmethod (as seen in Recipe 7.6).

    Discussion

    We discussed these block methods in more detail in Chapter 4, because arrays are the simplest and most common enumerable data type, and the most common. But almost any data structure can be enumerated, and a more complex data structure can be enumerated in more different ways.

    As you’ll see in Recipe 9.4, theEnumerablemethods, likedetect andinject, are actually implemented in terms ofeach. Thedetectandinjectmethods yield to the code block every element that comes out ofeach. The value of theyieldstatement is used to determine whether the element matches some criteria.

    In a method like detect, the iteration may stop once it finds an element that matches. In a method like find_all, the iteration goes through all elements, collecting the ones that match.

     

    Methods likecollectwork the same way, but instead of returning a subset of elements based on what the code block says, they collect the values returned by the code block in a new data structure, and return the data structure once the iteration is completed.

    If you’re using a particular object and you wish itscollectmethod used a different iterator, then you should turn the object into anEnumeratorand call itscollectmethod. But if you’re writing a class and you want to expose a newcollect-like method, you’ll have to define a new method.* In that case, the best solution is probably to expose a method that returns a customEnumerator: that way, your users can use all the methods ofEnumerable, not justcollect.

    See Also

    1. Recipe 4.5, “Sorting an Array”
    2. Recipe 4.11, “Getting the N Smallest Items of an Array”
    3. Recipe 4.15, “Partitioning or Classifying a Set”
    4. Recipe 7.6, “Changing the Way an Object Iterates”
    5. If all you want is to make your custom data structure support the methods of Enumerable, see Recipe 9.4, “Implementing Enumerable: Write One Method, Get 22 Free”

    Please check back next week for the conclusion of this article.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "Ruby Cookbook," published by O'Reilly. We...
     

    Buy this book now. This article is excerpted from chapter eight of the Ruby Cookbook, written by Lucas Carlson and Leonard Richardson (O'Reilly, 2006; ISBN: 0596523696). Check it out today at your favorite bookstore. Buy this book now.

    RUBY-ON-RAILS ARTICLES

    - Iterating and Incrementing Strings in Ruby
    - Comparing and Manipulating Strings in Ruby
    - Strings in Ruby
    - Ruby On Rails: Making Your First Dynamic Site
    - Ruby on Rails: Beginning Rails
    - Ruby: Modules, Mixins, Fixins, and Rails
    - Controlling Information Access with the Rail...
    - URLs, Filters and the Rails Action Controller
    - Flash and the Rails Action Controller
    - Rails Action Controller
    - Dropping and Sorting with AJAX and script.ac...
    - Drag and Drop with script.aculo.us and Rails
    - Introducing script.aculo.us
    - Ruby Classes and Objects
    - Ruby Loops






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 1 hosted by Hostway
    Stay green...Green IT