Update itertools recipes.
This commit is contained in:
parent
fd1b0930ce
commit
fc91aa28fd
|
@ -580,16 +580,19 @@ which incur interpreter overhead.
|
|||
"Return first n items of the iterable as a list"
|
||||
return list(islice(iterable, n))
|
||||
|
||||
def enumerate(iterable, start=0):
|
||||
return zip(count(start), iterable)
|
||||
|
||||
def tabulate(function, start=0):
|
||||
"Return function(0), function(1), ..."
|
||||
return map(function, count(start))
|
||||
|
||||
def consume(iterator, n):
|
||||
"Advance the iterator n-steps ahead. If n is none, consume entirely."
|
||||
collections.deque(islice(iterator, n), maxlen=0)
|
||||
# Use functions that consume iterators at C speed.
|
||||
if n is None:
|
||||
# feed the entire iterator into a zero-length deque
|
||||
collections.deque(iterator, maxlen=0)
|
||||
else:
|
||||
# advance to the emtpy slice starting at position n
|
||||
next(islice(iterator, n, n), None)
|
||||
|
||||
def nth(iterable, n, default=None):
|
||||
"Returns the nth item or a default value"
|
||||
|
@ -661,10 +664,9 @@ which incur interpreter overhead.
|
|||
seen = set()
|
||||
seen_add = seen.add
|
||||
if key is None:
|
||||
for element in iterable:
|
||||
if element not in seen:
|
||||
seen_add(element)
|
||||
yield element
|
||||
for element in filterfalse(seen.__contains__, iterable):
|
||||
seen_add(element)
|
||||
yield element
|
||||
else:
|
||||
for element in iterable:
|
||||
k = key(element)
|
||||
|
@ -677,3 +679,33 @@ which incur interpreter overhead.
|
|||
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
|
||||
# unique_justseen('ABBCcAD', str.lower) --> A B C A D
|
||||
return map(next, map(itemgetter(1), groupby(iterable, key)))
|
||||
|
||||
def iter_except(func, exception, first=None):
|
||||
""" Call a function repeatedly until an exception is raised.
|
||||
|
||||
Converts a call-until-exception interface to an iterator interface.
|
||||
Like __builtin__.iter(func, sentinel) but uses an exception instead
|
||||
of a sentinel to end the loop.
|
||||
|
||||
Examples:
|
||||
iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator
|
||||
iter_except(d.popitem, KeyError) # non-blocking dict iterator
|
||||
iter_except(d.popleft, IndexError) # non-blocking deque iterator
|
||||
iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue
|
||||
iter_except(s.pop, KeyError) # non-blocking set iterator
|
||||
|
||||
"""
|
||||
try:
|
||||
if first is not None:
|
||||
yield first() # For database APIs needing an initial cast to db.first()
|
||||
while 1:
|
||||
yield func()
|
||||
except exception:
|
||||
pass
|
||||
|
||||
Note, many of the above recipes can be optimized by replacing global lookups
|
||||
with local variables defined as default values. For example, the
|
||||
*dotproduct* recipe can be written as::
|
||||
|
||||
def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):
|
||||
return sum(map(mul, vec1, vec2))
|
||||
|
|
Loading…
Reference in New Issue