How to implement nested for loops in Python functional programming?
I’m thinking about applying the map function twice to allow it to act as a double for loop, but I don’t know if that makes sense.
Is this the solution to the problem?
For example, this is what I’m doing :
Imperative:
def degree(A):
n = len(A)
t = []
for i in range(n):
d = 0
for j in range(n):
d+=A[i][j]
t.append(d)
return t
Functionally:
def degree(A):
n = len(A)
t = []
map(lambda x,y:x+y,A)
If it’s a single for loop, then I’ll handle it like above. So I tried to implement a double map, but I don’t know how to construct it.
Any help would be appreciated!
Solution
You are summing an internal list A, so just apply sum to each nested list
in A
:
def degree(A):
return map(sum, A)
You might also consider using a list understanding or generator expression (depending on whether you need to delay generating results (map()
generates lists in Python 2, it delays work in Python 3):
def degree(A):
# returns a list
return [sum(row) for row in A]
def degree(A):
# returns a generator
return (sum(row) for row in A)
Otherwise you can generate i
and j
as Cartesian products, used itertools.product()
; However, you pass the tuple of integers to the callable map:
from itertools import product
map(lambda ij: A[ij[0]][ij[1]] ** 2, product(range(len(A)), 2))
This can be remedied by using itertools.starmap():
from itertools import product, starmap
starmap(lambda i, j: A[i][i] ** 2, product(range(len(A)), 2))
Neither produces a sum; I demonstrated a lambda
instead generating squares of the innermost values, so you get a long list of squares of all values, with no distinction between rows. This is how the mapping works, generating a value for each item processed in the input.
You can also nest map()
phones; Put inside map() in the external call map()
:
map(lambda r: map(lambda v: v ** 2, r), A)
Note, however, that this generates a lazy sequence of lazy objects in Python 3. Again, summation does not make sense in this case because there is no accumulation of results.
For the general accumulation of results in a sequence, you need to use functools.reduce()
function ; That callable applies callable to the next value in the run result and sequence. You can use your lambda x, y: x + y
to produce a sum function and map()
:
map(lambda r: reduce(lambda x, y: x + y, r, 0), A)
But for just summation, the reduce(lambda x, y: x + y
, <iterable>, 0) syntax is just a lengthy and slower way to spell sum(<iterable>).