Erin Wolpert
Erin Wolpert

Reputation: 383

Using map in Python

I'm trying to use the map Python function (I know I can use list comprehension but I was instructed to use map in this example) to take the row average of a two row matrix.

Here is what I think the answer should look like:

def average_rows2(mat):
    print( map( float(sum) / len , [mat[0],mat[1]] ) )
average_rows2([[4, 5, 2, 8], [3, 9, 6, 7]])

Right now, only the sum function works:

def average_rows2(mat):
    print( map( sum , [mat[0],mat[1]] ) )
average_rows2([[4, 5, 2, 8], [3, 9, 6, 7]])

The first problem is that adding the float() to the sum function gives the error:

TypeError: float() argument must be a string or a number

Which is weird because the elements of the resulting list should be integers since it successfully calculates the sum.

Also, adding / len to the sum function gives this error:

TypeError: unsupported operand type(s) for /: 'builtin_function_or_method' and 'builtin_function_or_method'

For this error, I tried * and // and it says that none are supported operand types. I don't understand why none of these would be supported.

Maybe this means that the map function doesn't take composite functions?

Upvotes: 3

Views: 802

Answers (3)

jonrsharpe
jonrsharpe

Reputation: 122169

The first argument has to be evaluated before it can be passed to map. This:

float(sum) / len

is causing you various errors as it doesn't make any sense to evaluate it on its own (unless you'd shadowed sum and len, which would be a different problem). You are trying to sum over one built-in function then divide by another! It therefore cannot be an argument.

Instead, make a function, e.g.:

lambda lst: float(sum(lst)) / len(lst)

This is a callable with a single argument, therefore can be used as the first argument to map, which will then apply it to each element in its second argument. You could also use a regular function, rather than an anonymous lambda (as now shown in https://stackoverflow.com/a/34831192/3001761).

Upvotes: 8

Nicholas
Nicholas

Reputation: 486

What map does is apply a given function to each element of a list. In your case, I think it's clearer to define this function (to calculate the average of a single row) separately, like so:

def average_of_one_row(r):
    return float(sum(r)) / len(r)

def average_of_each_row(mat):
    return map(average_of_one_row, mat)

print average_of_rows([[4, 5, 2, 8], [3, 9, 6, 7]])

Upvotes: 0

Vlad
Vlad

Reputation: 18643

This will work regardless of how many rows there are:

def average_rows(m):
    return map(lambda l: sum(l) / float(len(l)), m)
print average_rows([[4, 5, 2, 8], [3, 9, 6, 7]]) # [4.75, 6.25]

The function returns a list that's the result of applying the lambda to each element (row) of m.

The lambda expression lambda l: sum(l) / float(len(l)) is basically a function that takes a list and returns the average of its elements as a float. You could assign it to a variable and call it like a regular function:

avg = lambda l: sum(l) / float(len(l))
print avg([1, 2, 3])

Upvotes: 0

Related Questions