Difference between revisions of "Map"

From CS 61A Wiki
Jump to: navigation, search
[unchecked revision][unchecked revision]
Line 93: Line 93:
 
[5, 7, 9]
 
[5, 7, 9]
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
  
 
=====<code>multiply_by_each_other</code>=====
 
=====<code>multiply_by_each_other</code>=====
 
Suppose we wanted to multiple the elements of two lists by each other. <code>Map</code> would be an incredibly convenient way to do so! We'll define our lists, <code>list_a</code> and <code>list_b</code>, and our multiplication function, <code>multiply_by_each_other</code> as follows:
 
Suppose we wanted to multiple the elements of two lists by each other. <code>Map</code> would be an incredibly convenient way to do so! We'll define our lists, <code>list_a</code> and <code>list_b</code>, and our multiplication function, <code>multiply_by_each_other</code> as follows:
<syntaxhiglight lang="python">
+
 
 +
<syntaxhighlight lang="python">
 
def multiply_by_each_other(x, y):
 
def multiply_by_each_other(x, y):
 
   return x*y
 
   return x*y
Line 114: Line 116:
 
[10, 32, 60]
 
[10, 32, 60]
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
===Using <code>None</code> as a function (only for Python 2.7)===
 
===Using <code>None</code> as a function (only for Python 2.7)===
 
As stated before, using <code>None</code> as the passed argument function is analogous to using the <code>identity</code> function. And again, this only works for Python 2.7 and before! Attempting this in Python 3.2+ will result in a <code>'NoneType' object is not callable </code> error.
 
As stated before, using <code>None</code> as the passed argument function is analogous to using the <code>identity</code> function. And again, this only works for Python 2.7 and before! Attempting this in Python 3.2+ will result in a <code>'NoneType' object is not callable </code> error.

Revision as of 11:17, 25 June 2014

Map is a built-in Python higher-order function that applies a given function to all the items of an iterable.

Given a function and an iterable (often in the form of a list), Map works by (1) applying the function to each element of the iterable and (2) returning the result.

The Python 2.7 map built-in will always return a list, regardless of the type of iterable passed. The Python 3.2+ map built-in will return a map-object which can easily be converted into a list. Note that this is just one of the several inconsistencies of map across different versions of Python. Some code might work perfectly in 2.7, but fail in 3.2+!

Forms

General form

In Python, the most general form of the map function is as follows:

map(fn, itr)

where the function being applied is fn and the lone iterable is itr.

Alternate forms

In addition to the most general form, map can take many different shapes. The following are a few examples of these alternate forms and the assumptions they carry.

map(fn, itr1, itr2, ...)

When multiple iterables are offered, fn must take that many arguments. It will then apply the function to each of the iterables in parallel.

map(None, itr)

In Python 2.7 specifically, when the given function is None, map assumes the identity function. If more than one iterable is offered and the given function is None, map will create tuples using elements from each iterable in the final list. (e.g, the first element of the first iterable and the first element of the second iterable will be combined in a tuple to form the first element of the map's resultant list.) If we attempt to use None as our argument function in Python 3.3, the program will error!

Examples

Single argument functions

add_one

For the first example, we will use the function add_one and the basic 5-element list my_list which we will define as follows:

def add_one(x):
   return x+1
 
my_list = [1, 2, 3, 4, 5]

Mapping add_one to my_list in Python 2.7 would look something like this:

>>>map(add_one, my_list)
[2, 3, 4, 5, 6]

If we wanted to do the same in Python 3.2 or later, we would simply convert the result from a map object to a list, and it would look something like this:

>>>list(map(add_one, my_list)
[2, 3, 4, 5, 6]


multiply_by_two

Let's use another function, multiply_by_two (which we could have named double!), and a new list, new_list.

def multiply_by_two(x):
   return x*2
 
new_list = [1, 3, 5, 7, 9]

Just as in the add_one example, we have to adjust our code depending on the version of Python we want to use. Applying map in Python 2.7 and using our multiply_by_two function and new_list gives us the following:

>>>map(multiply_by_two, new_list)
[2, 6, 10, 14, 18]

As before, a change to Python 3.3 simply involves converting the map object to a more user-friendly list.

>>>list(map(multiply_by_two, new_list))
[2, 6, 10, 14, 18]

Multiple argument functions

Now we'll try a few examples where map takes in a multiple argument function.

add_two_things

In this example, we'll take a basic function, add_two_things, which does exactly as its namesake suggests. We'll also create the two lists: my_list and your_list, as defined below.

def add_two_things(x, y):
   return x+y
 
my_list = [1, 2, 3]
your_list = [4, 5, 6]

Using the map function with these arguments will combine components from matching indexes of the two lists, as so:

(in Python 2.7)

>>>map(add_two_things, my_list, your_list)
[5, 7, 9]

(or in Python 3.2+)

>>>list(map(add_two_things, my_list, your_list))
[5, 7, 9]


multiply_by_each_other

Suppose we wanted to multiple the elements of two lists by each other. Map would be an incredibly convenient way to do so! We'll define our lists, list_a and list_b, and our multiplication function, multiply_by_each_other as follows:

def multiply_by_each_other(x, y):
   return x*y
list_a = [2, 4, 6]
list_b = [5, 8, 10]
</syntaxhlightlight>
 
In Python 2.7, we can expect the following:
<syntaxhighlight lang="python">
>>>map(multiply_by_each_other, list_a, list_b)
[10, 32, 60]

And in Python 3.2+, we can expect the following:

>>>list(map(multiply_by_each_other, list_a, list_b))
[10, 32, 60]

Using None as a function (only for Python 2.7)

As stated before, using None as the passed argument function is analogous to using the identity function. And again, this only works for Python 2.7 and before! Attempting this in Python 3.2+ will result in a 'NoneType' object is not callable error.

A single iterable

In the case of a single list, map will simply return the identity of the list. We will define a_list as follows, then pass it into map. For clarification purposes, the code will assume to be using Python 2.7.

a_list = [7, 12, 33]
 
>>>map(None, a_list)
[7, 12, 33]
Multiple iterables

When multiple iterables are passed as arguments along with None into the map function, things get a little more complicated. Rather than return the individual lists, or line them end to end, map will create tuples at each index and create a list from these tuples. Each tuple includes the matching elements from each iterable. Imagine we create the following three lists, list_one, list_two, and list_three:

list_one = [1, 2, 3, 4]
list_two = [5, 7, 9, 11]
list_three = [12, 14, 16, 18]

We are assumed to be using Python 2.7, and can expect the following result:

>>>map(None, list_one, list_two, list_three)
[(1, 5, 12), (2, 7, 14), (3, 9, 16), (4, 11, 18)]

Notice that the first element from each list is combined into a tuple in the resulting list. The second tuple is a combination of the second elements, and so on.