Functional Programming Modules

itertools — functions creating iterators for efficient looping

Iterators terminating on the shortest input sequence

import itertools

L1 = [1,4,3,2,0,6,5,7,8,9]
T1 = (1,2,3,5,4,7,6,9)
W1 = "Agnieszka"
W2 = ["Jane", "Yu"]
E = [[1,2,3], [4,5], [6]]

#accumalate

print(L1)
Acc = itertools.accumulate(L1)
#adding values to prvs element
for each in Acc:
    print(each)

#output: 1 5 8 10 10 16	21 28 36 45
#explonation:
# Takes the first element Then adds the next ones
# 1 5 (1+4) 8 (5+3) 10 (8+2)
# 10 (10+0) 16 (10+6) 21 (16+5)...

Acc = itertools.accumulate(L1, max)
#max for each pair in list
for each in Acc:
    print(each)

#output: 1 4 4 4 4 6 6 7 8 9
#exlonation: 
# Takes the first element and compare with 
# second one then choose max
#max(1, 4)	max(4, 3)	max(4, 2)
# max(4, 0)	max(4, 6)	max(6, 5)
# max(6, 7)	max(7, 8)	max(8, 9).

#chain

# a list of odd numbers

TupleAndList = list(itertools.chain(L1,T1))
print(TupleAndList)
#output: [1, 4, 3, 2, 0, 6, 5, 7, 8, 9, 1, 2, 3, 5, 4, 7, 6, 9]
# adding all elements from T1 to list of L1 
# sorted as it is defined originally 

W = list(itertools.chain.from_iterable(W1))
print("W =", W)
#or
print("W =", W, end="\n\n")
#output: W = ['A', 'g', 'n', 'i', 'e', 's', 'z', 'k', 'a']

W = list(itertools.chain.from_iterable(W2))
print("W =", W)
#or
print("W =", W, end="\n\n")
#W = ['J', 'a', 'n', 'e', 'Y', 'u']

W = list(itertools.chain.from_iterable(E))
print("W =", W)
#W = [1, 2, 3, 4, 5, 6]

#compress
fruits= ["grapes", "orange", "strawberry", "plum",
         "wild strawberry", "cranberry"]
red = [False, False, True, False, True, True]

result = list(itertools.compress(fruits, red))
print(result)
#['strawberry', 'wild strawberry', 'cranberry']


#dropwhile and filterfalse

n = [i > 5  for i  in L1]
print(n)
#output:
#[False, False, False, False, False, True, 
#False, True, True, True]
def more_than_five(n):
    return (n > 5)

print(list(itertools.dropwhile(more_than_five, T1)))
print(list(itertools.filterfalse(more_than_five, T1)))

elems = [("Mascara", "Maybelline"),
         ("Mascara", "MaxFactor"),
         ("Lipstick", "Joanna"),
         ("Lipstick", "Eveline")]


# groupby

grp = itertools.groupby(elems, lambda x : x[0])
for key, group in grp:
    key_and_group = {key : list(group)}
    print(key_and_group)


# pairwise

print(list(itertools.pairwise(L1)))
#[(1, 4), (4, 3), (3, 2), (2, 0), ..., (8, 9)]
print(list(itertools.pairwise(W)))
#[('A', 'g'), ('g', 'n'), ('n', 'i'), ... ('k', 'a')]
z = zip(T1,L1)
#list(z):
#[(1, 1), (2, 4), (3, 3), (5, 2), (4, 0), (7, 6), ...
print(list(itertools.pairwise(z))) #[]
#output: pairs in pairs
# [((1, 1), (2, 4)), ((2, 4), (3, 3)), ((3, 3),...

# starmap

# adds 2 to each element in list
mp = list(map(lambda x: x + 2, T1))
print(mp)

x = list(itertools.pairwise(L1))
stmp = list(itertools.starmap(lambda x, y:x + y, x))
print(stmp)

# tee

it = itertools.tee(iter(L1),5) # n is max of range

print ("The iterators are : ")
for i in range (1,4):
#first position in range is starto of range of list,
# second is where it stops.
    print (list(it[i]))

# zip_longest

print(len(L1)) #10
print(len(T1)) #8

z = zip(T1,L1)
print(len(list(z))) #8
z = zip(L1,T1)
print(len(list(z))) #8

zl = list(itertools.zip_longest(T1,L1))
print(zl)
#output: [(1, 1), (2, 4), ..., (None, 8), (None, 9)]
print(len(zl)) #10

Infinite iterators

# count

print(L1)
#[1, 4, 3, 2, 0, 6, 5, 7, 8, 9]
print(len(L1)) #10

iCounter = itertools.count(start = 0, step = 2)
print("Even list:" , list(next(iCounter) for _ in L1))
#output Even list: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
#in itertool.count the specified list L1 is define as range
print(len(list(next(iCounter) for _ in L1))) #output: 10

# cycle

initial_question = input("Do the procedure (y/n)?  "  )
if initial_question.lower() == "y":
    x = itertools.cycle([1,2,3])
    print(f"Processor: {next(x)}: " + Mascara.name)
    print(f"Processor: {next(x)}: " + Mascara.color)
    print(f"Processor: {next(x)}: " + Mascara.serial_number)
    print(f"Processor: {next(x)}: " + Lipstick.name)
    print(f"Processor: {next(x)}: " + Lipstick.color)
    

elif initial_question.lower() == "n":
    print("end")
    processing = False
else:
    print("wrong input")

'''
output: 
Processor: 1: Maybelline
Processor: 2: extra black
Processor: 3: 1234567890
Processor: 1: Joanna
Processor: 2: red'''

# repeat

print(list(itertools.repeat(W1,3)))
# output: ['Agnieszka', 'Agnieszka', 'Agnieszka']
print(list(itertools.repeat((L1[1:3] + L1[3:5]),5)))
# output: [[4, 3, 2, 0], [4, 3, 2, 0], ...., [4, 3, 2, 0]]

Combinatoric iterators

# product

print(L1[0:2], L1[4:6]) #[1, 4] [0, 6]
def alternating_pairing(l1, l2):
    # return the list of all the computed tuple
    # using the product() method
    return list(itertools.product(l1, l2))

# Driver Function
if __name__ == "__main__":
    l1 = L1[0:2]
    l2 = L1[4:6]
    print(alternating_pairing(l1, l2))
    # output: [(1, 0), (1, 6), (4, 0), (4, 6)]


# permutation

p = itertools.permutations(W1[0:3])
# Print the obtained permutations
for i in list(p):
    print(i)

p = itertools.permutations(L1[0:3])
# Print the obtained permutations
for i in list(p):
    print(i)

# combinations

from itertools import (combinations,
                       combinations_with_replacement)

print(list(combinations(range(3), 1)))
# output: [(0,), (1,), (2,)]
print(list(combinations(range(3), 2)))
# output: [(0, 1), (0, 2), (1, 2)]

print(list(combinations_with_replacement(W1[1:3], 2)))
# output: [('g', 'g'), ('g', 'n'), ('n', 'n')]