Take several iterators as arguments and returns a single iterator
In [2]:
from itertools import chain
for i in chain([1,2,3], ['a', 'b', 'c']):
print(i, end=' ')
In [3]:
from itertools import *
def make_iterables_to_chain():
yield [1, 2, 3]
yield ['a', 'b', 'c']
for i in chain.from_iterable(make_iterables_to_chain()):
print(i, end=' ')
print()
use zip_longest to zip a tuple
In [4]:
from itertools import *
r1 = range(3)
r2 = range(2)
for r12 in zip(r1,r2):
print(r12)
print()
In [5]:
print(list(zip_longest(r1,r2)))
In [6]:
print(list(zip_longest(r1,r2, fillvalue='a')))
islice returns selcted item by index
In [9]:
from itertools import *
print('Stop at 5')
for i in islice(range(100), 5):
print(i, end =' ')
print('\n')
print('start at 5, and stop at 10')
for i in islice(range(100), 5, 10):
print(i, end=' ')
print('\n')
print('by ten to 100')
for i in islice(range(100), 0,100, 10):
print(i, end=' ')
print('\n')
tee returns several independent iterators(default to 2)
In [13]:
from itertools import *
r = islice(count(), 5)
r1,r2 = tee(r)
print('r1', list(r1))
print('r2', list(r2))
In [16]:
from itertools import *
values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
for i in starmap(lambda x, y: (x, y, x * y), values):
print('{} * {} = {}'.format(*i))
In [18]:
from itertools import *
for i in zip(count(1), ['a', 'b', 'c']):
print(i)
count() take start and step arguments
In [19]:
import fractions
from itertools import *
start = fractions.Fraction(1, 3)
step = fractions.Fraction(1, 3)
for i in zip(count(start, step), ['a', 'b', 'c']):
print('{}: {}'.format(*i))
In [20]:
from itertools import *
for i in zip(range(7), cycle(['a', 'b', 'c'])):
print(i)
In [21]:
from itertools import *
for i in repeat('over-and-over', 5):
print(i)
In [22]:
from itertools import *
def should_drop(x):
print('Testing:', x)
return x < 1
for i in dropwhile(should_drop, [-1, 0, 1, 2, -2]):
print('Yielding:', i)
dropwhile() does not filter every item of the input; after the condition is false the first time, all of the remaining items in the input are returned.
In [23]:
from itertools import *
def should_take(x):
print('Testing:', x)
return x < 2
for i in takewhile(should_take, [-1, 0, 1, 2, -2]):
print('Yielding:', i)
As soon as should_take() returns False, takewhile() stops processing the input.
compress() offers another way to filter the contents of an iterable. Instead of calling a function, it uses the values in another iterable to indicate when to accept a value and when to ignore it.
In [24]:
from itertools import *
every_third = cycle([False, False, True])
data = range(1, 10)
for i in compress(data, every_third):
print(i, end=' ')
print()
In [26]:
import functools
from itertools import *
import operator
import pprint
@functools.total_ordering
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return '({}, {})'.format(self.x, self.y)
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __gt__(self, other):
return (self.x, self.y) > (other.x, other.y)
# Create a dataset of Point instances
data = list(map(Point,
cycle(islice(count(), 3)),
islice(count(), 7)))
print('Data:')
pprint.pprint(data, width=35)
print()
In [28]:
print('Grouped, unsorted:')
for k, g in groupby(data, operator.attrgetter('x')):
print(k, list(g))
print()
In [30]:
# Sort the data
data.sort()
print('Sorted:')
pprint.pprint(data, width=35)
print()
In [31]:
print('Grouped, sorted:')
for k, g in groupby(data, operator.attrgetter('x')):
print(k, list(g))
print()
The input sequence needs to be sorted on the key value in order for the groupings to work out as expected.
Nested for loops that iterate over multiple sequences can often be replaced with product(), which produces a single iterable whose values are the Cartesian product of the set of input values.
In [32]:
from itertools import *
import pprint
FACE_CARDS = ('J', 'Q', 'K', 'A')
SUITS = ('H', 'D', 'C', 'S')
DECK = list(
product(
chain(range(2, 11), FACE_CARDS),
SUITS,
)
)
for card in DECK:
print('{:>2}{}'.format(*card), end=' ')
if card[1] == SUITS[-1]:
print()