Updated On : Nov-17,2019  itertools, iterators, co…

# Overview¶

It provides a list of `iterator` for some common tasks like permutations, combinations, infinite iterators, cycle looping, etc.

In [1]:
```import itertools
from datetime import datetime
import time
```

### Infinite Iterators:¶

• `count(start=0,step=1)` - Keeps on increasing count by `step` from `start` until loop is stopped by some condition.
• `cycle(iterable)` - keeps on looping through `iterable` infinite times. After the last element has used it again starts from the first one like a cycle.
• `repeat(object[,times=None])` - Keeps on repeating object infinite times until stopped by some loop. If times are provided as some integer then it repeats that many times.
In [2]:
```result = []
for i in itertools.count(5, 5):
if i <= 100:
result.append(i)
else:
break
print(result)

result = []
for i in itertools.cycle(range(1,6)):
if len(result) < 15:
result.append(i)
else:
break
print(result)

result = []
for i in itertools.cycle(['B','O','B']):
if len(result) < 15:
result.append(i)
else:
break
print(result)

print(list(itertools.repeat('A', 5)))
print(list(itertools.repeat([1,2], 5)))
print(list(itertools.repeat({'key':'val'}, 7)))
```
```[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
['B', 'O', 'B', 'B', 'O', 'B', 'B', 'O', 'B', 'B', 'O', 'B', 'B', 'O', 'B']
['A', 'A', 'A', 'A', 'A']
[[1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]
[{'key': 'val'}, {'key': 'val'}, {'key': 'val'}, {'key': 'val'}, {'key': 'val'}, {'key': 'val'}, {'key': 'val'}]
```

### Other short sequence terminators:¶

• `accumulate(iterable[,func])` - It returns accumulated sum of numbers if `func` is not provided else applies `binary func` to elements of `iterable`.
• `chain(*iterables)` - It loops through all `iterables` passed as arguments and returns elements of each one by one in sequence they were given input.
• `compress(data,selectors)` - It loop through `data` one by one and returns only that elements for which element with same index in `selectors` return `True`.
In [3]:
```print(list(itertools.accumulate(range(5,15))))
print(list(itertools.accumulate(range(5,15), lambda x,y : x*y)))
print(list(itertools.accumulate(range(5,15), lambda x,y : y/x)))
print(list(itertools.accumulate('ABCD')))
print(list(itertools.accumulate('ABCD', lambda x,y : [x,y])))

print(list(itertools.chain(range(1,4),range(4, 1,-1),'ABCDE')))

print(list(itertools.compress(range(5,0,-1),[True,False,True,False,True])))
print(list(itertools.compress(range(5,0,-1),[True,None,None,False,True])))
print(list(itertools.compress(range(5,0,-1),[0,1,1,1,0])))
print(list(itertools.compress(range(5,0,-1),[[],[1,2],[],[1,2,3],[]])))
print(list(itertools.compress(range(5,0,-1),[{},{'key':'val'},{'key':'val'},{},{}])))
```
```[5, 11, 18, 26, 35, 45, 56, 68, 81, 95]
[5, 30, 210, 1680, 15120, 151200, 1663200, 19958400, 259459200, 3632428800]
[5, 1.2, 5.833333333333334, 1.3714285714285712, 6.562500000000001, 1.5238095238095235, 7.218750000000002, 1.662337662337662, 7.820312500000002, 1.7902097902097898]
['A', 'AB', 'ABC', 'ABCD']
['A', ['A', 'B'], [['A', 'B'], 'C'], [[['A', 'B'], 'C'], 'D']]
[1, 2, 3, 4, 3, 2, 'A', 'B', 'C', 'D', 'E']
[5, 3, 1]
[5, 1]
[4, 3, 2]
[4, 2]
[4, 3]
```
• `dropwhile(predicate,iterable)` - It drops element as long as `predicate condition` is `True` and then it returns all elements.
• `filterfalse(predicate,iterable)` - It returns only those elements from `iterable` for which `predicate condition` is `False`.
In [4]:
```print(list(itertools.dropwhile(lambda x: x<2, range(1,6))))
print(list(itertools.dropwhile(lambda x: x == 2, range(1,6)))) ## Make a note here that first condition itself is False hence returns all elements
print(list(itertools.dropwhile(lambda x: (x**2) < 5, range(1,6))))
print(list(itertools.dropwhile(lambda x : x in ['A','E','I','O','U'], 'EABCD')))

print(list(itertools.filterfalse(lambda x: x%2==0, range(1,6))))
print(list(itertools.filterfalse(lambda x: x//2 < 2, range(1,6))))
print(list(itertools.filterfalse(None, range(6))))
print(list(itertools.filterfalse(lambda x : x in ['A','E','I','O','U'], 'ABCDE')))
```
```[2, 3, 4, 5]
[1, 2, 3, 4, 5]
[3, 4, 5]
['B', 'C', 'D']
[1, 3, 5]
[4, 5]
[0]
['B', 'C', 'D']
```
• `groupby(iterable,key=None)` - Returns an iterator which consists of `key, group` pair from `iterable` based on function provided as `key` which generates `key` in pair. If `key` is not provided then it's set to identity function(`lambda x: x`). `iterable` should be sorted to get proper results/grouping. Elements should be in sorted order to get proper groups.
In [5]:
```for key,group in itertools.groupby([2,2,2,3,3,4,4]):
print(str(key)+ ' : ' + str(list(group)))
for key,group in itertools.groupby(['Arial','Ariel','Bad','Bed','Cat','Catch'],key=lambda x: x[0]):
print(str(key)+ ' : ' + str(list(group)))

class Employee(object):
def __init__(self, name, age):
self.name = name
self.age = age

def __str__(self):
return self.name + ' : , Age : '+str(self.age)

e1 = Employee('Sunny',27)
e2 = Employee('Sumit',27)
e3 = Employee('Anup',35)
e4 = Employee('Ashwin',35)
e5 = Employee('Rohit',38)
e6 = Employee('Irfan',38)
e7 = Employee('Ethesh',22)
e8 = Employee('Kaushal',45)

for key,group in itertools.groupby([e1,e2,e3,e4,e5,e6,e7,e8], key=lambda x: x.age):
group_desc = [str(item) for item in group]
print(str(key)+ ' : ' + str(group_desc))

for key,group in itertools.groupby([e1,e2,e3,e4,e5,e6,e7,e8], key=lambda x: x.name[0]):
group_desc = [str(item) for item in group]
print(str(key)+ ' : ' + str(group_desc))
```
```2 : [2, 2, 2]
3 : [3, 3]
4 : [4, 4]
A : ['Arial', 'Ariel']
C : ['Cat', 'Catch']
27 : ['Sunny : , Age : 27', 'Sumit : , Age : 27']
35 : ['Anup : , Age : 35', 'Ashwin : , Age : 35']
38 : ['Rohit : , Age : 38', 'Irfan : , Age : 38']
22 : ['Ethesh : , Age : 22']
45 : ['Kaushal : , Age : 45']
S : ['Sunny : , Age : 27', 'Sumit : , Age : 27']
A : ['Anup : , Age : 35', 'Ashwin : , Age : 35']
R : ['Rohit : , Age : 38']
I : ['Irfan : , Age : 38']
E : ['Ethesh : , Age : 22']
K : ['Kaushal : , Age : 45']
```
• `islice(iterable, stop)` - Loops through `iterable` and returns element from begining till `stop` index.
• `islice(iterable, start,stop[,step])` - Loops through `iterable` from `start` index till `stop` index using `step` for item skipping
• `starmap(function,iterable)` - executes `function` using each argouments of `iterable` as argument to `function`.
• `takewhile()` - It's reverse of `dropwhile()` function. It returns element until condition is `True` whereas dropwhile() drops element while condition is `True` and then returns elements.
In [6]:
```print(list(itertools.islice('ABCDE',3)))
print(list(itertools.islice('ABCDE',0,2)))
print(list(itertools.islice('ABCDE',0,None, 3)))

print(list(itertools.starmap(lambda x: x%2, [(2,),(3,),(4,),(5,),(6,),(7,),(8,)])))
print(list(itertools.starmap(lambda x: datetime.fromtimestamp(x), [(6,),(60,),(3600,)])))
print(list(itertools.starmap(lambda x: time.gmtime(x),[(6,),(60,),(3600,)])))

print(list(itertools.takewhile(lambda x: x<2, range(1,6))))
print(list(itertools.takewhile(lambda x: x == 2, range(1,6)))) ## Make a note here that first condition itself is False hence returns no elements
print(list(itertools.takewhile(lambda x: (x**2) < 5, range(1,6))))
print(list(itertools.takewhile(lambda x : x in ['A','E','I','O','U'], 'EABCD')))
```
```['A', 'B', 'C']
['A', 'B']
['A', 'D']
[0, 1, 0, 1, 0, 1, 0]
[datetime.datetime(1970, 1, 1, 0, 0, 6), datetime.datetime(1970, 1, 1, 0, 1), datetime.datetime(1970, 1, 1, 1, 0)]
[time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=6, tm_wday=3, tm_yday=1, tm_isdst=0), time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=1, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0), time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=1, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)]
[1]
[]
[1, 2]
['E', 'A']
```
• `tee(iterable,n=2)` - It returns n independent iterables from single `iterable`.
• `zip_longest(*iterable, fill_value=None)` - It's same as `zip()` function but returns elements same as longest sequence and fills value specified by `fill_value` in other small lists.
In [7]:
```result = itertools.tee([1,2,3,4], 4)
print([list(item) for item in result ])

result = itertools.tee('ABCDE', 3)
print([list(item) for item in result ])

print(list(itertools.zip_longest([1,2,3,4,5,6],[1,2,4],[1,2,3,4,5])))
print(list(itertools.zip_longest([1,2,3,4,5,6],[1,2,4],[1,2,3,4,5],'NONE')))
print(list(itertools.zip_longest([1,2,3,4,5,6],[1,2,4],[1,2,3,4,5],'NA')))
```
```[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
[['A', 'B', 'C', 'D', 'E'], ['A', 'B', 'C', 'D', 'E'], ['A', 'B', 'C', 'D', 'E']]
[(1, 1, 1), (2, 2, 2), (3, 4, 3), (4, None, 4), (5, None, 5), (6, None, None)]
[(1, 1, 1, 'N'), (2, 2, 2, 'O'), (3, 4, 3, 'N'), (4, None, 4, 'E'), (5, None, 5, None), (6, None, None, None)]
[(1, 1, 1, 'N'), (2, 2, 2, 'A'), (3, 4, 3, None), (4, None, 4, None), (5, None, 5, None), (6, None, None, None)]
```

### Conbinatorics iterators:¶

• `product(*iterables)` - Returns cartesian product of input `iterables`. To compute product of `iterable` with itself specify `repeat` with number of times you want to repeat.
• `permutations(iterable,r=None)` - It returns all possible permutations of lenght `r` of `iterable`. If `r` is not specified then all possible permutation of whole `iterable` is returned.
• `combinations(iterable,r)` - Returns all combinations of length `r` of `iterable`.
• `combinations_with_replacement(iterable,r)` - Returns all combinations of length `r` of `iterable` with allowing replacement more than once.
In [8]:
```print(list(itertools.product([1,2,3,4],[4,3,2,1])))
print(list(itertools.product([1,2,3,4],[4,3,2,1],[7,8,9])))
print(list(itertools.product([1,2,3,4],[4,3,])))
print(list(itertools.product([1,2,3,4],[4,3,],repeat=2)))
print(list(itertools.product('CBA','ABC')))
print(list(itertools.product([1,2,3,4],repeat=3)))
```
```[(1, 4), (1, 3), (1, 2), (1, 1), (2, 4), (2, 3), (2, 2), (2, 1), (3, 4), (3, 3), (3, 2), (3, 1), (4, 4), (4, 3), (4, 2), (4, 1)]
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 3, 7), (1, 3, 8), (1, 3, 9), (1, 2, 7), (1, 2, 8), (1, 2, 9), (1, 1, 7), (1, 1, 8), (1, 1, 9), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 3, 7), (2, 3, 8), (2, 3, 9), (2, 2, 7), (2, 2, 8), (2, 2, 9), (2, 1, 7), (2, 1, 8), (2, 1, 9), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 3, 7), (3, 3, 8), (3, 3, 9), (3, 2, 7), (3, 2, 8), (3, 2, 9), (3, 1, 7), (3, 1, 8), (3, 1, 9), (4, 4, 7), (4, 4, 8), (4, 4, 9), (4, 3, 7), (4, 3, 8), (4, 3, 9), (4, 2, 7), (4, 2, 8), (4, 2, 9), (4, 1, 7), (4, 1, 8), (4, 1, 9)]
[(1, 4), (1, 3), (2, 4), (2, 3), (3, 4), (3, 3), (4, 4), (4, 3)]
[(1, 4, 1, 4), (1, 4, 1, 3), (1, 4, 2, 4), (1, 4, 2, 3), (1, 4, 3, 4), (1, 4, 3, 3), (1, 4, 4, 4), (1, 4, 4, 3), (1, 3, 1, 4), (1, 3, 1, 3), (1, 3, 2, 4), (1, 3, 2, 3), (1, 3, 3, 4), (1, 3, 3, 3), (1, 3, 4, 4), (1, 3, 4, 3), (2, 4, 1, 4), (2, 4, 1, 3), (2, 4, 2, 4), (2, 4, 2, 3), (2, 4, 3, 4), (2, 4, 3, 3), (2, 4, 4, 4), (2, 4, 4, 3), (2, 3, 1, 4), (2, 3, 1, 3), (2, 3, 2, 4), (2, 3, 2, 3), (2, 3, 3, 4), (2, 3, 3, 3), (2, 3, 4, 4), (2, 3, 4, 3), (3, 4, 1, 4), (3, 4, 1, 3), (3, 4, 2, 4), (3, 4, 2, 3), (3, 4, 3, 4), (3, 4, 3, 3), (3, 4, 4, 4), (3, 4, 4, 3), (3, 3, 1, 4), (3, 3, 1, 3), (3, 3, 2, 4), (3, 3, 2, 3), (3, 3, 3, 4), (3, 3, 3, 3), (3, 3, 4, 4), (3, 3, 4, 3), (4, 4, 1, 4), (4, 4, 1, 3), (4, 4, 2, 4), (4, 4, 2, 3), (4, 4, 3, 4), (4, 4, 3, 3), (4, 4, 4, 4), (4, 4, 4, 3), (4, 3, 1, 4), (4, 3, 1, 3), (4, 3, 2, 4), (4, 3, 2, 3), (4, 3, 3, 4), (4, 3, 3, 3), (4, 3, 4, 4), (4, 3, 4, 3)]
[('C', 'A'), ('C', 'B'), ('C', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('A', 'A'), ('A', 'B'), ('A', 'C')]
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4), (1, 4, 1), (1, 4, 2), (1, 4, 3), (1, 4, 4), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 1), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 1, 1), (3, 1, 2), (3, 1, 3), (3, 1, 4), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 1), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 1), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 1, 1), (4, 1, 2), (4, 1, 3), (4, 1, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 1), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 4, 4)]
```
In [9]:
```print(list(itertools.permutations('ABCDE', r=2))) ## Order of elements does matter in permutations
print(list(itertools.permutations('ABC')))
```
```[('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'A'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'A'), ('C', 'B'), ('C', 'D'), ('C', 'E'), ('D', 'A'), ('D', 'B'), ('D', 'C'), ('D', 'E'), ('E', 'A'), ('E', 'B'), ('E', 'C'), ('E', 'D')]
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
```
In [10]:
```print(list(itertools.combinations('ABCDE', r=2))) ## Order of elements does not matter in combintations
print(list(itertools.combinations_with_replacement('ABCDE', r=2))) ## Make a note that element was replaced hence there are extra entry of element with itself.
print(list(itertools.combinations('ABC', r=3)))
```
```[('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'D'), ('C', 'E'), ('D', 'E')]
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'C'), ('C', 'D'), ('C', 'E'), ('D', 'D'), ('D', 'E'), ('E', 'E')]
[('A', 'B', 'C')]
```
Sunny Solanki

## Support Us

Thank You for visiting our website. If you like our work, please support us so that we can keep on creating new tutorials/blogs on interesting topics (like AI, ML, Data Science, Python, Digital Marketing, SEO, etc.) that can help people learn new things faster. You can support us by clicking on the Coffee button at the bottom right corner. We would appreciate even if you can give a thumbs-up to our article in the comments section below.

## Want to Share Your Views? Have Any Suggestions?

If you want to

• provide some suggestions on topic