Section 14.4. Iterators in JavaScript


14.4. Iterators in JavaScript

Python's iteration protocol is very useful. It makes it possible to easily handle large data sets that get reduced down to results of a reasonable size. In addition, the itertools module provides a number of extremely convenient functions. If you haven't checked out itertools in Python, you definitely should.

Or, you can play around with MochiKit.Iter's extensive implementation of the same functions. To use iteration tools, however, you need to have iterators.

Just as in Python, an iterator in JavaScript will define a next() method that will throw a StopIteration exception when it is done processing. An iterable object will either define an iter() method or use registerIteratorFactory to tell MochiKit how to get an iterator for specific kinds of objects. MochiKit.Iter itself uses registerIteratorFactory to allow JavaScript arrays to participate in the iteration protocol.

For your own JavaScript code, you will likely just define iter on your prototype to return an iterator for your code. registerIteratorFactory is handy when you're trying to iterate over an object that is not directly in your control.

14.4.1. Making an Iterator

Here is a simple example that lets you iterate over the parameters in a query string:

Let's take a look at this in use:

  >>> qs = new queryObj("name=Hosty%20Most&city=South%20Barton");   [object Object]   >>> i = iter(qs)   [object Object]   >>> i.next()   ["name", "Hosty Most"]   >>> i.next()   ["city", "South Barton"]


This is similar to how you define and use iterators in Python.

14.4.2. Functions from Itertools

MochiKit has faithful reproductions of all your favorites from Python's itertools.

The groupby function takes an iterable and a key function and returns an iterable where each item that comes out is a pair: the key, and an iterator for the values that match that key. The items are assumed to be sorted on that key in advance.

Here is an example that exercises groupby:

  numbers = [2, 4, 6, 8, 10, 1, 3, 5, 7, 9];   i = groupby(numbers, function(val) {       if (val % 2 == 0) {           return "even";       } else {           return "odd";       }   });   try {       while (info = i.next()) {           writeln("Group: " + info[0]);           j = info[1];           try {               while (num = j.next()) {                   writeln(num);               }           } catch (e) {               if (e != StopIteration) {                   throw e;               }           }       }   } catch (e) {       if (e != StopIteration) {           throw e;       }   }


Here is the output you see when you run this in the interactive interpreter:

 Group: even  2  4  6  8  10  Group: odd  1  3  5  7  9


MochiKit also has a version of this that is not found in itertools. groupby_as_array will return an array of arrays rather than an iterator of iterators.

Something that is found in Python, but not itertools specifically, is the list function. MochiKit.Iter implements this function for JavaScript. It returns a list (array) from an iterator.

Another function that is a Python built-in but is found in MochiKit.Iter is reduce(func, i[, initial]). reduce returns a single value by calling func with either the last returned value or the initial value and i.next(). This makes it easy to compute a result based on a lot of data that you iterate over.

The following functions are ones that MochiKit.Iter offers that are also in Python's itertools module or Python built-ins. These functions all return iterators, and the return values mentioned are what those iterators will return:

  • chain(i1, i2, ...) Returns elements from i1, then the elements from i2, and so on

  • count(n=0) Iterates incrementally starting at n

  • cycle(i) Saves each element returned and starts over from the beginning once i is exhausted

  • dropwhile(func, i) Starts returning elements from i once func(i.next()) returns false

  • ifilter(func, i) Returns only the elements where func(i.next()) is true

  • ifilterfalse(func, i) Returns only the elements where func(i.next()) is false

  • imap(func, i1[, i2, ...]) Returns func(i1.next(), i2.next(), ...)

  • islice(i, [start,] stop[, step]) Returns the elements that fall within the slice (just as in Python's [start:stop:step] notation)

  • izip(i1[, i2, i3, ...]) Like zip, aggregates the elements from each of the iterators

  • range([start,] stop[, step]) Like count, but it returns a range of numbers

  • repeat(obj[, n]) Keeps returning obj, or returns obj n times

  • reversed(i) Returns a reversed list from i

  • sorted(i[, cmp]) Returns a sorted array from iterable, using the cmp function for comparison if provided

  • sum(i, start=0) Returns the sum of the elements starting at start

  • takewhile(func, i) Returns the elements from i while func(i.next()) is true

  • tee(i, n=2) Splits i into n iterators that you can use independently (don't use the original after you call tee, however)

14.4.3. Functions Unique to MochiKit.Iter

As useful as Python's itertools module is, MochiKit.Iter adds some other functions, too.

  • applymap(func, seq[, self]) Calls func with each element of seq (in the context of self, if supplied), returning a list of the return values from the calls to func

  • every(i, func) Returns true if func(i.next()) is true for each item in the iterator

  • exhaust(i) Use up the iterable without saving the results anywhere

  • forEach(i, func[, self]) Call func for each element of i without saving the return values

  • iextend(lst, i) Adds the elements from i to lst

  • some(i, func) Returns true if func(i.next()) is true for at least one item




Rapid Web Applications with TurboGears(c) Using Python to Create Ajax-Powered Sites
Rapid Web Applications with TurboGears: Using Python to Create Ajax-Powered Sites
ISBN: 0132433885
EAN: 2147483647
Year: 2006
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net