Difference between revisions of "Map"

From CS 61A Wiki
Jump to: navigation, search
[checked revision][checked revision]
m ({{C-class}})
(copyedit)
Line 1: Line 1:
 
{{DISPLAYTITLE:map}}
 
{{DISPLAYTITLE:map}}
 
{{C-class}}
 
{{C-class}}
'''Map''' is a built-in [[Python]] [[higher-order function]] that applies a given function to all the items of an iterable.
+
'''map''' is a built-in [[Python]] [[higher-order function]] that applies a given function to all the items of an [[iterable]]. The returned result differs between Python 2 and Python 3:
 
+
* In Python 2, <code>map</code> returns a [[list]], regardless of the type of iterable passed.
Given a function and an iterable (often in the form of a [[list]]), <code>Map</code> works by (1) applying the function to each element of the iterable and (2) returning the result.
+
* In Python 3, <code>map</code> returns an iterable ''map object'', which can be converted into a [[sequence]] using the appropriate constructor (e.g., <code>list(...)</code>, <code>tuple(...)</code>).
 
+
The [https://docs.python.org/2/library/functions.html#map Python 2.7 map built-in] will always return a ''list'', regardless of the type of iterable passed. The [https://docs.python.org/3.2/library/functions.html#map 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 <code>map</code> across different versions of Python. Some code might work perfectly in 2.7, but fail in 3.2+!
+
  
 
==Forms==
 
==Forms==
 
===General form===
 
===General form===
In Python, the most general form of the <code>map</code> function is as follows:
+
The most general form of the <code>map</code> function is:
 
<syntaxhighlight lang="python">map(fn, itr)</syntaxhighlight>
 
<syntaxhighlight lang="python">map(fn, itr)</syntaxhighlight>
  
where the function being applied is <code>fn</code> and the lone iterable is <code>itr</code>.
+
where the function being applied is <code>fn</code> and the lone iterable is <code>itr</code>. <code>fn</code> must be a one-argument function.
  
 
===Alternate forms===
 
===Alternate forms===
In addition to the most general form, <code>map</code> can take many different shapes. The following are a few examples of these alternate forms and the assumptions they carry.
+
<code>map</code> has alternate forms:
 
+
*<blockquote><source lang="python">map(fn, itr1, itr2, ...)</source></blockquote> When multiple iterables are offered, <code>fn</code> must take that many arguments. It will then apply the function to each of the iterables in parallel.
<syntaxhighlight lang="python">map(fn, itr1, itr2, ...)</syntaxhighlight>
+
*<blockquote><syntaxhighlight lang="python">map(None, itr)</syntaxhighlight></blockquote> In Python 2, when the given function is <code>None</code>, <code>map</code> assumes the identity function (<code>lambda x: x</code>). This only works for Python 2 — attempting this in Python 3 will result in a <code>'NoneType' object is not callable </code> error.
When multiple iterables are offered, <code>fn</code> must take that many arguments. It will then apply the function to each of the iterables in parallel.  
+
:If more than one iterable is provided, <code>map</code> will create [[tuple]]s 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 returned list).
 
+
<syntaxhighlight lang="python">map(None, itr)</syntaxhighlight>  
+
In Python 2.7 specifically, when the given function is <code>None</code>, <code>map</code> assumes the [https://docs.python.org/2/library/functions.html#id identity] function.
+
If more than one iterable is offered and the given function is <code>None</code>, <code>map</code> will create [[tuple|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 <code>map</code>'s resultant list.)
+
'''If we attempt to use <code>None</code> as our argument function in Python 3.3, the program will error!'''
+
  
 
==Examples==
 
==Examples==
===Single argument functions===
+
===Single-argument functions===
 
====<code>add_one</code>====
 
====<code>add_one</code>====
For the first example, we will use the function <code>add_one</code> and the basic 5-element list <code>my_list</code> which we will define as follows:
+
For the first example, we will use the function <code>increment</code> and the 5-element <code>lst</code>:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
def add_one(x):
+
def increment(x):
   return x+1
+
   return x + 1
 
+
lst = [1, 2, 3, 4, 5]
my_list = [1, 2, 3, 4, 5]
+
 
</syntaxhighlight>
 
</syntaxhighlight>
Mapping <code>add_one</code> to <code>my_list</code> in Python 2.7 would look something like this:
+
 
 +
Mapping <code>increment</code> to <code>lst</code> in Python 2 would look like this:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>map(add_one, my_list)
+
>>> map(increment, lst)
 
[2, 3, 4, 5, 6]  
 
[2, 3, 4, 5, 6]  
 
</syntaxhighlight>
 
</syntaxhighlight>
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:
+
 
 +
To do the same in Python 3, we convert the result from a map object to a list:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>list(map(add_one, my_list)
+
>>> list(map(increment, lst)
 
[2, 3, 4, 5, 6]
 
[2, 3, 4, 5, 6]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
+
====<code>double</code>====
====<code>multiply_by_two</code>====
+
Let's use another function, <code>double</code> and a list <code>lst</code>:
Let's use another function, <code>multiply_by_two</code> (which we could have named <code>double</code>!), and a new list, <code>new_list</code>.
+
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
def multiply_by_two(x):
+
def double(x):
   return x*2
+
   return x * 2
 
+
lst = [1, 3, 5, 7, 9]
new_list = [1, 3, 5, 7, 9]
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Just as in the <code>add_one</code> example, we have to adjust our code depending on the version of Python we want to use.
+
Applying <code>map</code> on this list:
Applying <code>map</code> in Python 2.7 and using our <code>multiply_by_two</code> function and <code>new_list</code> gives us the following:
+
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>map(multiply_by_two, new_list)
+
# Python 2
 +
>>> map(double, lst)
 
[2, 6, 10, 14, 18]
 
[2, 6, 10, 14, 18]
</syntaxhighlight>
 
  
As before, a change to Python 3.3 simply involves converting the ''map object'' to a more user-friendly ''list''.
+
# Python 3
<syntaxhighlight lang="python">
+
>>> list(map(double, lst))
>>>list(map(multiply_by_two, new_list))
+
 
[2, 6, 10, 14, 18]
 
[2, 6, 10, 14, 18]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Multiple argument functions===
+
===Multiple-argument functions===
Now we'll try a few examples where <code>map</code> takes in a multiple argument function.
+
Now we'll try a few examples where <code>map</code> takes in a multiple-argument function and multiple iterables.
 +
 
 
=====<code>add_two_things</code>=====
 
=====<code>add_two_things</code>=====
In this example, we'll take a basic function, <code>add_two_things</code>, which does exactly as its namesake suggests. We'll also create the two lists: <code>my_list</code> and <code>your_list</code>, as defined below.
+
In this example, we use a function, <code>add_two_things</code>, which does exactly as its name suggests. We also create two lists: <code>lst1</code> and <code>lst2</code>:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
def add_two_things(x, y):
 
def add_two_things(x, y):
   return x+y
+
   return x + y
 
+
lst1 = [1, 2, 3]
my_list = [1, 2, 3]
+
lst2 = [4, 5, 6]
your_list = [4, 5, 6]
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Using the <code>map</code> function with these arguments will combine components from matching indexes of the two lists, as so:
+
Using the <code>map</code> function with these arguments will combine items from matching indices of the two lists:
 
+
(in Python 2.7)
+
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>map(add_two_things, my_list, your_list)
+
# Python 2
 +
>>> map(add_two_things, lst1, lst2)
 
[5, 7, 9]
 
[5, 7, 9]
</syntaxhighlight>
 
  
(or in Python 3.2+)
+
# Python 3
<syntaxhighlight lang="python">
+
>>> list(map(add_two_things, lst1, lst2))
>>>list(map(add_two_things, my_list, your_list))
+
 
[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 multiply 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>lst1</code> and <code>lst2</code>, and our multiplication function, <code>multiply_by_each_other</code>:
 
+
 
<syntaxhighlight 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
list_a = [2, 4, 6]
+
lst1 = [2, 4, 6]
list_b = [5, 8, 10]
+
lst2 = [5, 8, 10]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
In Python 2.7, we can expect the following:
+
Using <code>map</code>:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>map(multiply_by_each_other, list_a, list_b)
+
# Python 2
 +
>>> map(multiply_by_each_other, lst1, lst2)
 
[10, 32, 60]
 
[10, 32, 60]
</syntaxhighlight>
 
  
And in Python 3.2+, we can expect the following:
+
# Python 3
<syntaxhighlight lang="python">
+
>>> list(map(multiply_by_each_other, list_a, list_b))
>>>list(map(multiply_by_each_other, list_a, list_b))
+
 
[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 the function (only for Python 2)===
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.
+
Using <code>None</code> as the function is analogous to using the <code>identity</code> function.
 +
 
 
=====A single iterable=====
 
=====A single iterable=====
In the case of a single list, <code>map</code> will simply return the identity of the list. We will define <code>a_list</code> as follows, then pass it into <code>map</code>. For clarification purposes, the code will assume to be using Python 2.7.
+
In the case of a single list, <code>map</code> will simply return the identity of the list. We define <code>lst</code> and then pass it into <code>map</code>:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
a_list = [7, 12, 33]
+
>>> lst = [7, 12, 33]
 
+
>>> map(None, lst)
>>>map(None, a_list)
+
 
[7, 12, 33]
 
[7, 12, 33]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=====Multiple iterables=====
 
=====Multiple iterables=====
When multiple iterables are passed as arguments along with <code>None</code> into the <code>map</code> function, things get a little more complicated. Rather than return the individual lists, or line them end to end, <code>map</code> will create tuples at each index and create a list from these tuples. Each tuple includes the matching elements from each iterable.
+
Multiple iterables can passed as arguments along with <code>None</code> into the <code>map</code> function. We create three lists:
Imagine we create the following three lists, <code>list_one</code>, <code>list_two</code>, and <code>list_three</code>:
+
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
list_one = [1, 2, 3, 4]
+
lst1 = [1, 2, 3, 4]
list_two = [5, 7, 9, 11]
+
lst2 = [5, 7, 9, 11]
list_three = [12, 14, 16, 18]
+
lst3 = [12, 14, 16, 18]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
We are assumed to be using Python 2.7, and can expect the following result:
+
Using <code>map</code>:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
>>>map(None, list_one, list_two, list_three)
+
>>> map(None, lst1, lst2, lst3)
 
[(1, 5, 12), (2, 7, 14), (3, 9, 16), (4, 11, 18)]
 
[(1, 5, 12), (2, 7, 14), (3, 9, 16), (4, 11, 18)]
 
</syntaxhighlight>
 
</syntaxhighlight>
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.
+
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.
 +
 
 +
== Sources ==
 +
* https://docs.python.org/2/library/functions.html#map
 +
* https://docs.python.org/3.2/library/functions.html#map

Revision as of 10:35, 4 July 2014

map is a built-in Python higher-order function that applies a given function to all the items of an iterable. The returned result differs between Python 2 and Python 3:

  • In Python 2, map returns a list, regardless of the type of iterable passed.
  • In Python 3, map returns an iterable map object, which can be converted into a sequence using the appropriate constructor (e.g., list(...), tuple(...)).

Forms

General form

The most general form of the map function is:

map(fn, itr)

where the function being applied is fn and the lone iterable is itr. fn must be a one-argument function.

Alternate forms

map has alternate forms:

  • 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, when the given function is None, map assumes the identity function (lambda x: x). This only works for Python 2 — attempting this in Python 3 will result in a 'NoneType' object is not callable error.
If more than one iterable is provided, 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 returned list).

Examples

Single-argument functions

add_one

For the first example, we will use the function increment and the 5-element lst:

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

Mapping increment to lst in Python 2 would look like this:

>>> map(increment, lst)
[2, 3, 4, 5, 6]

To do the same in Python 3, we convert the result from a map object to a list:

>>> list(map(increment, lst)
[2, 3, 4, 5, 6]

double

Let's use another function, double and a list lst:

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

Applying map on this list:

# Python 2
>>> map(double, lst)
[2, 6, 10, 14, 18]
 
# Python 3
>>> list(map(double, lst))
[2, 6, 10, 14, 18]

Multiple-argument functions

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

add_two_things

In this example, we use a function, add_two_things, which does exactly as its name suggests. We also create two lists: lst1 and lst2:

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

Using the map function with these arguments will combine items from matching indices of the two lists:

# Python 2
>>> map(add_two_things, lst1, lst2)
[5, 7, 9]
 
# Python 3
>>> list(map(add_two_things, lst1, lst2))
[5, 7, 9]
multiply_by_each_other

Suppose we wanted to multiply the elements of two lists by each other. map would be an incredibly convenient way to do so! We'll define our lists, lst1 and lst2, and our multiplication function, multiply_by_each_other:

def multiply_by_each_other(x, y):
   return x * y
lst1 = [2, 4, 6]
lst2 = [5, 8, 10]

Using map:

# Python 2
>>> map(multiply_by_each_other, lst1, lst2)
[10, 32, 60]
 
# Python 3
>>> list(map(multiply_by_each_other, list_a, list_b))
[10, 32, 60]

Using None as the function (only for Python 2)

Using None as the function is analogous to using the identity function.

A single iterable

In the case of a single list, map will simply return the identity of the list. We define lst and then pass it into map:

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

Multiple iterables can passed as arguments along with None into the map function. We create three lists:

lst1 = [1, 2, 3, 4]
lst2 = [5, 7, 9, 11]
lst3 = [12, 14, 16, 18]

Using map:

>>> map(None, lst1, lst2, lst3)
[(1, 5, 12), (2, 7, 14), (3, 9, 16), (4, 11, 18)]

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.

Sources