Streaming and functional programming¶
In [4]:
# standard libraries
import math
import os
import gzip
from glob import glob
import itertools as it
# 3rd party libraries
import toolz as tz
import toolz.curried as c
import numpy as np
Understanding itertools
¶
repeat
¶
In [5]:
for i, item in enumerate(it.repeat('abc')):
print(item)
if i >= 4:
break
abc
abc
abc
abc
abc
In [6]:
list(it.repeat('abc', 5))
Out[6]:
['abc', 'abc', 'abc', 'abc', 'abc']
Replicating behavior using reular Python¶
In [7]:
def repeat(obj, n=None):
if n is None:
while True:
yield obj
else:
for i in range(n):
yield obj
In [8]:
for i, item in enumerate(repeat('abc')):
print(item)
if i >= 4:
break
abc
abc
abc
abc
abc
In [9]:
list(repeat('abc', 5))
Out[9]:
['abc', 'abc', 'abc', 'abc', 'abc']
cycle
¶
In [10]:
list(it.islice(it.cycle('abc'), 10))
Out[10]:
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a']
Replicating behavior using regular Python¶
In [11]:
def cycle(obj):
while True:
yield from obj
In [12]:
list(it.islice(cycle('abc'), 10))
Out[12]:
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a']
count
¶
In [13]:
list(it.islice(it.count(), 5))
Out[13]:
[0, 1, 2, 3, 4]
In [14]:
list(it.islice(it.count(2), 5))
Out[14]:
[2, 3, 4, 5, 6]
In [15]:
list(it.islice(it.count(2,2), 5))
Out[15]:
[2, 4, 6, 8, 10]
Replicating behavior using regular Python¶
In [16]:
def count(start=0, step=1):
while True:
yield start
start += step
In [17]:
list(it.islice(it.count(), 5))
Out[17]:
[0, 1, 2, 3, 4]
In [18]:
list(it.islice(count(2), 5))
Out[18]:
[2, 3, 4, 5, 6]
In [19]:
list(it.islice(count(2,2), 5))
Out[19]:
[2, 4, 6, 8, 10]
chain
¶
In [20]:
list(it.islice(it.chain(range(3), 'abc', it.count()), 10))
Out[20]:
[0, 1, 2, 'a', 'b', 'c', 0, 1, 2, 3]
Replicating behavior with regular Python¶
In [21]:
def chain(*args):
for arg in args:
yield from arg
In [22]:
list(it.islice(chain(range(3), 'abc', it.count()), 10))
Out[22]:
[0, 1, 2, 'a', 'b', 'c', 0, 1, 2, 3]
chain.from_iterable
¶
In [23]:
list(it.islice(it.chain.from_iterable([range(3), 'abc', it.count()]),10))
Out[23]:
[0, 1, 2, 'a', 'b', 'c', 0, 1, 2, 3]
Replicating behavior with regular Python¶
In [24]:
def chain_from_iterable(args):
for arg in args:
yield from arg
In [25]:
list(it.islice(chain_from_iterable([range(3), 'abc', it.count()]),10))
Out[25]:
[0, 1, 2, 'a', 'b', 'c', 0, 1, 2, 3]
product
¶
In [26]:
list(it.product('ab', range(2), 'AB'))
Out[26]:
[('a', 0, 'A'),
('a', 0, 'B'),
('a', 1, 'A'),
('a', 1, 'B'),
('b', 0, 'A'),
('b', 0, 'B'),
('b', 1, 'A'),
('b', 1, 'B')]
Replicating behavior with regular Python¶
Note: Just as with lists, addition for tuples is concatenation.
In [27]:
('a', 0) + ('A',)
Out[27]:
('a', 0, 'A')
In [28]:
def product(*args):
if not args:
yield ()
else:
for items in product(*args[:-1]):
for item in args[-1]:
yield tuple(items) + (item,)
In [29]:
list(product('ab', range(2), 'AB'))
Out[29]:
[('a', 0, 'A'),
('a', 0, 'B'),
('a', 1, 'A'),
('a', 1, 'B'),
('b', 0, 'A'),
('b', 0, 'B'),
('b', 1, 'A'),
('b', 1, 'B')]
permuations
¶
In [30]:
list(it.permutations('abc', 2))
Out[30]:
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
In [31]:
list(it.permutations('abc'))
Out[31]:
[('a', 'b', 'c'),
('a', 'c', 'b'),
('b', 'a', 'c'),
('b', 'c', 'a'),
('c', 'a', 'b'),
('c', 'b', 'a')]
Replicating behavior with regular Python¶
In [32]:
def permutations(xs, n=None):
if n is None:
n = len(xs)
args = repeat(xs, n)
for item in product(*args):
if len(set(item)) == n:
yield item
In [33]:
list(it.permutations('abc', 2))
Out[33]:
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
In [34]:
list(permutations('abc'))
Out[34]:
[('a', 'b', 'c'),
('a', 'c', 'b'),
('b', 'a', 'c'),
('b', 'c', 'a'),
('c', 'a', 'b'),
('c', 'b', 'a')]