JMartinez
JMartinez

Reputation: 123

Mapping arrays in Python using map, lambda, and functional programming workflows

I'm trying to understand how functional programming languages work, and I decided to take the approach of program in a functional way in python, as it is the language in which I feel more comfortable.

I'm trying to, given an array of arrays and a function with 2 params, get two sentences with the two elements in each array.

I cannot figure out how to do it without nesting lambdas, but even using them:

def sentence( x, y):
    return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]

output = map(lambda a: map(lambda b: map(lambda c,d: sentence(c,d),b),a),matrix)

Of course, because a I am a old fashioned imperative programmer, I try to get the output with the good old for loop. Sure there's a better way but...

#print(output)
for i in output:
    #print(i)
    for j in i:
        #print(j)
        for k in j:
            print(k)

At the end I only get this result:

  File "fp.py", line 12, in <module>
    for k in j:
TypeError: <lambda>() missing 1 required positional argument: 'd'

So yes, I guess I'm doing something wrong passing the values to the function, but I cannot guess why.

Any ideas?

Upvotes: 2

Views: 17027

Answers (5)

Nathan Vērzemnieks
Nathan Vērzemnieks

Reputation: 5603

You don't need lambdas at all, but you do need to unpack your arguments, which has changed in recent versions of python. The code below will work in older and newer versions both:

def sentence(x_y):
    x, y = x_y
    return "Here is a sentence with {} and {}".format(x, y)

matrix = [['a', 'b'], ['c', 'd']]
output = list(map(sentence, matrix))

Upvotes: -2

Arseniy
Arseniy

Reputation: 1778

  1. Python style guide recommends using list comprehensions instead of map/reduce
  2. String formatting using percent operator is obsolete, consider using format() method
  3. the code you need is this simple one-liner

    output = [" this string contains {} and {}".format(x, y) for (x, y) in matrix]

Upvotes: 4

splash58
splash58

Reputation: 26153

You do it too difficult

def sentence( x, y):
    return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]
# c will get sublists consequently
output = [sentence(*c)  for c in matrix]
print(output) # [' this string contains a and b', ' this string contains c and d']

You can avoid for in code above by

output = list(map(lambda c: sentence(*c), matrix))

Upvotes: 1

Snark
Snark

Reputation: 1664

You have a couple of issues, these structures aren't nested deeply enough to warrant the nested loops.

You need 1 map for each level of list you wish to process, so if you want to process a list, you need a map, if you want to process a list of lists, you need 2 and so on.

In this case you most likely only want to process the top level (effectively this is because you want each list in the top level to become a sentence).

def sentence( x, y):
return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]

output = map(lambda a: sentence(a[0],a[1]), matrix)

# Print the top level
for i in output:
    print(i)

Upvotes: 1

9000
9000

Reputation: 40894

Your last lambda will not receive two arguments, because it's fed the elements of b. It must receive one argument.

Such a ladder of lambdas does not look nice in any language. With named functions, it's much more readable.

Upvotes: 0

Related Questions