4 @note Source http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66448
13 def ordered_itr(collection):
15 >>> [v for v in ordered_itr({"a": 1, "b": 2})]
17 >>> [v for v in ordered_itr([3, 1, 10, -20])]
20 if isinstance(collection, types.DictType):
21 keys = list(collection.iterkeys())
24 yield key, collection[key]
26 values = list(collection)
32 def itercat(*iterators):
34 Concatenate several iterators into one.
36 >>> [v for v in itercat([1, 2, 3], [4, 1, 3])]
44 def iterwhile(func, iterator):
46 Iterate for as long as func(value) returns true.
47 >>> through = lambda b: b
48 >>> [v for v in iterwhile(through, [True, True, False])]
51 iterator = iter(iterator)
53 next = iterator.next()
59 def iterfirst(iterator, count=1):
61 Iterate through 'count' first values.
63 >>> [v for v in iterfirst([1, 2, 3, 4, 5], 3)]
66 iterator = iter(iterator)
67 for i in xrange(count):
71 def iterstep(iterator, n):
73 Iterate every nth value.
75 >>> [v for v in iterstep([1, 2, 3, 4, 5], 1)]
77 >>> [v for v in iterstep([1, 2, 3, 4, 5], 2)]
79 >>> [v for v in iterstep([1, 2, 3, 4, 5], 3)]
82 iterator = iter(iterator)
86 for dummy in xrange(n-1):
90 def itergroup(iterator, count, padValue = None):
92 Iterate in groups of 'count' values. If there
93 aren't enough values, the last result is padded with
96 >>> for val in itergroup([1, 2, 3, 4, 5, 6], 3):
100 >>> for val in itergroup([1, 2, 3, 4, 5, 6], 3):
104 >>> for val in itergroup([1, 2, 3, 4, 5, 6, 7], 3):
109 >>> for val in itergroup("123456", 3):
113 >>> for val in itergroup("123456", 3):
114 ... print repr("".join(val))
118 paddedIterator = itertools.chain(iterator, itertools.repeat(padValue, count-1))
119 nIterators = (paddedIterator, ) * count
120 return itertools.izip(*nIterators)
123 def xzip(*iterators):
124 """Iterative version of builtin 'zip'."""
125 iterators = itertools.imap(iter, iterators)
127 yield tuple([x.next() for x in iterators])
130 def xmap(func, *iterators):
131 """Iterative version of builtin 'map'."""
132 iterators = itertools.imap(iter, iterators)
136 # Emulate map behaviour, i.e. shorter
137 # sequences are padded with None when
138 # they run out of values.
140 for i in range(len(iterators)):
141 iterator = iterators[i]
146 yield iterator.next()
148 except StopIteration:
152 args = tuple(values())
153 if not values_left[0]:
158 def xfilter(func, iterator):
159 """Iterative version of builtin 'filter'."""
160 iterator = iter(iterator)
162 next = iterator.next()
167 def xreduce(func, iterator, default=None):
168 """Iterative version of builtin 'reduce'."""
169 iterator = iter(iterator)
171 prev = iterator.next()
172 except StopIteration:
175 for next in iterator:
177 prev = func(prev, next)
179 return func(prev, default)
183 def daterange(begin, end, delta = datetime.timedelta(1)):
185 Form a range of dates and iterate over them.
188 begin -- a date (or datetime) object; the beginning of the range.
189 end -- a date (or datetime) object; the end of the range.
190 delta -- (optional) a datetime.timedelta object; how much to step each iteration.
191 Default step is 1 day.
195 if not isinstance(delta, datetime.timedelta):
196 delta = datetime.timedelta(delta)
198 ZERO = datetime.timedelta(0)
214 class LazyList(object):
216 A Sequence whose values are computed lazily by an iterator.
218 Module for the creation and use of iterator-based lazy lists.
219 this module defines a class LazyList which can be used to represent sequences
220 of values generated lazily. One can also create recursively defined lazy lists
221 that generate their values based on ones previously generated.
223 Backport to python 2.5 by Michael Pust
226 __author__ = 'Dan Spitz'
228 def __init__(self, iterable):
229 self._exhausted = False
230 self._iterator = iter(iterable)
234 """Get the length of a LazyList's computed data."""
235 return len(self._data)
237 def __getitem__(self, i):
238 """Get an item from a LazyList.
239 i should be a positive integer or a slice object."""
240 if isinstance(i, int):
241 #index has not yet been yielded by iterator (or iterator exhausted
242 #before reaching that index)
246 raise ValueError('cannot index LazyList with negative number')
249 #LazyList slices are iterators over a portion of the list.
250 elif isinstance(i, slice):
251 start, stop, step = i.start, i.stop, i.step
252 if any(x is not None and x < 0 for x in (start, stop, step)):
253 raise ValueError('cannot index or step through a LazyList with'
255 #set start and step to their integer defaults if they are None.
261 def LazyListIterator():
266 else (lambda: count < stop)
271 #slices can go out of actual index range without raising an
276 return LazyListIterator()
278 raise TypeError('i must be an integer or slice')
281 """return an iterator over each value in the sequence,
282 whether it has been computed yet or not."""
286 """Return an iterator over the values in a LazyList that have
287 already been computed."""
288 return self[:len(self)]
290 def exhaust(self, index = None):
291 """Exhaust the iterator generating this LazyList's values.
292 if index is None, this will exhaust the iterator completely.
293 Otherwise, it will iterate over the iterator until either the list
294 has a value for index or the iterator is exhausted.
299 ind_range = itertools.count(len(self))
301 ind_range = range(len(self), index + 1)
303 for ind in ind_range:
305 self._data.append(self._iterator.next())
306 except StopIteration: #iterator is fully exhausted
307 self._exhausted = True
311 class RecursiveLazyList(LazyList):
313 def __init__(self, prod, *args, **kwds):
314 super(RecursiveLazyList, self).__init__(prod(self, *args, **kwds))
317 class RecursiveLazyListFactory:
319 def __init__(self, producer):
322 def __call__(self, *a, **kw):
323 return RecursiveLazyList(self._gen, *a, **kw)
328 Decorator for creating a RecursiveLazyList subclass.
329 This should decorate a generator function taking the LazyList object as its
330 first argument which yields the contents of the list in order.
332 >>> #fibonnacci sequence in a lazy list.
337 ... for a, b in itertools.izip(lst, lst[1:]):
340 >>> #now fibs can be indexed or iterated over as if it were an infinitely long list containing the fibonnaci sequence
343 >>> #prime numbers in a lazy list.
345 ... def primegen(lst):
347 ... for candidate in itertools.count(3): #start at next number after 2
348 ... #if candidate is not divisible by any smaller prime numbers,
350 ... if all(candidate % p for p in lst.computed()):
353 >>> #same for primes- treat it like an infinitely long list containing all prime numbers.
354 >>> primes = primegen()
355 >>> print fibs[0], fibs[1], fibs[2], primes[0], primes[1], primes[2]
357 >>> print list(fibs[:10]), list(primes[:10])
358 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
360 return RecursiveLazyListFactory(gen)
366 >>> misc.validate_decorator(map_func)
371 result = itertools.imap(f, args)
376 def reduce_func(function):
379 >>> misc.validate_decorator(reduce_func(lambda x: x))
386 result = reduce(function, f(args))
394 @note Python Version <2.5
396 >>> any_([True, True])
398 >>> any_([True, False])
400 >>> any_([False, False])
404 for element in iterable:
412 @note Python Version <2.5
414 >>> all_([True, True])
416 >>> all_([True, False])
418 >>> all_([False, False])
422 for element in iterable:
428 def for_every(pred, seq):
430 for_every takes a one argument predicate function and a sequence.
431 @param pred The predicate function should return true or false.
432 @returns true if every element in seq returns true for predicate, else returns false.
434 >>> for_every (lambda c: c > 5,(6,7,8,9))
437 @author Source:http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52907
446 def there_exists(pred, seq):
448 there_exists takes a one argument predicate function and a sequence.
449 @param pred The predicate function should return true or false.
450 @returns true if any element in seq returns true for predicate, else returns false.
452 >>> there_exists (lambda c: c > 5,(6,7,8,9))
455 @author Source:http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52907
464 def func_repeat(quantity, func, *args, **kwd):
466 Meant to be in connection with "reduce"
468 for i in xrange(quantity):
469 yield func(*args, **kwd)
472 def function_map(preds, item):
474 Meant to be in connection with "reduce"
476 results = (pred(item) for pred in preds)
481 def functional_if(combiner, preds, item):
483 Combines the result of a list of predicates applied to item according to combiner
485 @see any, every for example combiners
487 pass_bool = lambda b: b
489 bool_results = function_map(preds, item)
490 return combiner(pass_bool, bool_results)
493 def pushback_itr(itr):
495 >>> list(pushback_itr(xrange(5)))
499 >>> itr = pushback_itr(xrange(5))
502 ... if first and i == 2:
504 ... print itr.send(i)
514 >>> itr = pushback_itr(xrange(5))
517 ... if first and i == 2:
519 ... print itr.send(i)
520 ... print itr.send(i)
531 >>> itr = pushback_itr(xrange(5))
536 >>> print itr.send(10)
542 >>> print itr.send(20)
544 >>> print itr.send(30)
546 >>> print itr.send(40)
552 >>> print itr.send(50)
564 maybePushedBack = yield item
566 while queue or maybePushedBack is not None:
567 if maybePushedBack is not None:
568 queue.append(maybePushedBack)
569 maybePushedBack = yield None
572 maybePushedBack = yield item
575 def itr_available(queue, initiallyBlock = False):
578 while not queue.empty():
579 yield queue.get_nowait()
582 if __name__ == "__main__":
584 print doctest.testmod()