forked from presnick/RunestoneServer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
423 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
.. Copyright (C) Paul Resnick. Permission is granted to copy, distribute | ||
and/or modify this document under the terms of the GNU Free Documentation | ||
License, Version 1.3 or any later version published by the Free Software | ||
Foundation; with Invariant Sections being Forward, Prefaces, and | ||
Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of | ||
the license is included in the section entitled "GNU Free Documentation | ||
License". | ||
Exercises | ||
--------- | ||
|
||
|
||
Write equivalent code using map instead of the manual accumulation below | ||
|
||
.. activecode:: map_exercise_1 | ||
|
||
things = [3, 5, -4, 7] | ||
|
||
accum = [] | ||
for thing in things: | ||
accum.append(thing+1) | ||
print accum | ||
|
||
Use manual accumulation to define the lengths function below. | ||
|
||
.. activecode:: map_exercise_2 | ||
|
||
def lengths(strings): | ||
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths | ||
of strings in the input list. Use manual accumulation!""" | ||
# fill in this function's definition to make the test pass. | ||
|
||
import test | ||
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3]) | ||
|
||
|
||
Now define lengths using map instead. | ||
|
||
.. activecode:: map_exercise_3 | ||
|
||
def lengths(strings): | ||
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths | ||
of strings in the input list. Use map!""" | ||
# fill in this function's definition to make the test pass. | ||
|
||
import test | ||
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3]) | ||
|
||
Now define lengths using a list comprehension instead. | ||
|
||
.. activecode:: listcomp_exercise_1 | ||
|
||
def lengths(strings): | ||
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths | ||
of strings in the input list. Use a list comprehension!""" | ||
# fill in this function's definition to make the test pass. | ||
|
||
import test | ||
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3]) | ||
|
||
|
||
.. activecode:: filter_1 | ||
|
||
things = [3, 5, -4, 7] | ||
# write code to produce a list of only the positive things, [3, 5, 7], via manual accumulation | ||
|
||
.. activecode:: filter_2 | ||
|
||
things = [3, 5, -4, 7] | ||
# write code to produce a list of only the positive things, [3, 5, 7], via manual accumulation | ||
|
||
# define longwords using manual accumulation | ||
|
||
.. activecode:: filter_3 | ||
|
||
def longwords(strings): | ||
"""Return a shorter list of strings containing only the strings with more than four characters. Use manual accumulation.""" | ||
# write your code here | ||
|
||
import test | ||
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"]) | ||
|
||
# define longwords using filter | ||
|
||
.. activecode:: filter_4 | ||
|
||
def longwords(strings): | ||
"""Return a shorter list of strings containing only the strings with more than four characters. Use the filter function.""" | ||
# write your code here | ||
|
||
import test | ||
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"]) | ||
|
||
# define longwords using a list comprehension | ||
|
||
.. activecode:: listcomp_exercise_2 | ||
|
||
def longwords(strings): | ||
"""Return a shorter list of strings containing only the strings with more than four characters. Use a list comprehension.""" | ||
# write your code here | ||
|
||
import test | ||
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"]) | ||
|
||
|
||
Now combine lengths with longwords to make a function that returns the lengths of those strings that have at least 4 characters. Try it first with a list comprehension. | ||
|
||
.. activecode:: listcomp_exercise_3 | ||
|
||
def longlengths(strings): | ||
return None | ||
|
||
import test | ||
test.testEqual(longlengths(["Hello", "hi", "bye", "wonderful"]), [5, 9]) | ||
|
||
Now try doing it using map and filter. | ||
|
||
.. activecode:: listcomp_exercise_4 | ||
|
||
def longlengths(strings): | ||
return None | ||
|
||
import test | ||
test.testEqual(longlengths(["Hello", "hi", "bye", "wonderful"]), [5, 9]) | ||
|
||
Write a function that takes a list of numbers and returns the sum of the squares of all the numbers. First try it using an accumulator pattern. | ||
|
||
.. activecode:: reduce_exercise_2 | ||
|
||
def sumSquares(L): | ||
return None | ||
|
||
nums = [3, 2, 2, -1, 1] | ||
|
||
import test | ||
test.testEqual(sumSquares(nums), 19) | ||
|
||
Now, try it using map and sum | ||
|
||
.. activecode:: reduce_exercise_3 | ||
|
||
def sumSquares(L): | ||
return None | ||
|
||
nums = [3, 2, 2, -1, 1] | ||
|
||
import test | ||
test.testEqual(sumSquares(nums), 19) | ||
|
||
|
||
Finally, try doing it using reduce | ||
|
||
.. activecode:: reduce_exercise_3 | ||
|
||
def sumSquares(L): | ||
return None | ||
|
||
nums = [3, 2, 2, -1, 1] | ||
|
||
import test | ||
test.testEqual(sumSquares(nums), 19) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
.. Copyright (C) Paul Resnick. Permission is granted to copy, distribute | ||
and/or modify this document under the terms of the GNU Free Documentation | ||
License, Version 1.3 or any later version published by the Free Software | ||
Foundation; with Invariant Sections being Forward, Prefaces, and | ||
Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of | ||
the license is included in the section entitled "GNU Free Documentation | ||
License". | ||
.. _list_comp_chap: | ||
|
||
Introduction: Map, Filter, Reduce and List Comprehensions | ||
========================================================= | ||
|
||
Let's revisit the :ref:`accumulator pattern <accum_pattern>`. We have frequently taken a list and produced another list from it that contains either a subset of the items or a transformed version of each item. When each item is transformed we say that the operation is a **mapping, or just a map** of the original list. When some items are omitted, we call it a **filter**. | ||
|
||
Python provides built-in functions ``map`` and ``filter``. Python also provides a new syntax, called **list comprehensions**, that lets you express a mapping and/or filtering operation. Just as with named functions and lambda expressions, some students seem to find it easier to think in terms of the map and filter functions, while other students find it easier to read and write list comprehensions. You'll learn both ways; one may even help you understand the other. Most python programmers use list comprehensions, so make sure you learn to read those. In this course, you can choose to learn to write list comprehensions or to use map and filter, whichever you prefer. You should learn to read both list comprehensions and map/filter. | ||
|
||
Other common accumulator patterns on lists ``reduce`` or aggregate all the values into a single value. | ||
|
||
Map, filter, and reduce are commands that you would use in high-performance computing on big datasets. See `MapReduce on Wikipedia <http://en.wikipedia.org/wiki/MapReduce>`_. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
.. Copyright (C) Paul Resnick Brad. Permission is granted to copy, distribute | ||
and/or modify this document under the terms of the GNU Free Documentation | ||
License, Version 1.3 or any later version published by the Free Software | ||
Foundation; with Invariant Sections being Forward, Prefaces, and | ||
Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of | ||
the license is included in the section entitled "GNU Free Documentation | ||
License". | ||
List Comprehensions | ||
------------------- | ||
|
||
Python provides an alternative way to do map and filter operations, called a **list comprehension**. Many programmers find them easier to understand and write. List comprehensions are concise ways to create lists from other lists. The general syntax is:: | ||
|
||
[<expression> for <item> in <sequence> if <condition>] | ||
|
||
where the if clause is optional. For example, | ||
|
||
.. activecode:: listcomp_7 | ||
|
||
things = [2, 5, 9] | ||
|
||
yourlist = [value * 2 for value in things] | ||
|
||
print yourlist | ||
|
||
The expression is ``value * 2``. The item variable is ``value`` and the sequence is ``things``. This is an alternative way to perform a mapping operation. As with ``map``, each item in the sequence is transformed into an item in the new list. Instead of the iteration happening automatically, however, we have adopted the syntax of the for loop which may make it easier to understand. | ||
|
||
Just as in a regular for loop, the part of the statement ``for value in things`` says to execute some code once for each item in things. Each time that code is executed, ``value`` is bound to one item from ``things``. The code that is executed each time is the expression at the beginning, ``value * 2``, rather than a block of code indented underneath the for statement. The other difference from a regular for loop is that each time the expression is evaluated, the resulting value is appended to a list. That happens automatically, without the programmer explicitly initializing an empty list or appending each item. | ||
|
||
The ``if`` clause of a list comprehension can be used to do a filter operation. To perform a pure filter operation, the expression can be simply the variable that is bound to each item. For example, the following list comprehension will keep only the positive numbers from the original list. | ||
|
||
.. activecode:: listcomp_8 | ||
|
||
def keep_evens(nums): | ||
new_list = [num for num in nums if num % 2 == 0] | ||
return new_list | ||
|
||
print keep_evens([3, 4, 6, 7, 0, 1]) | ||
|
||
You can also combine map and filter operations by chaining them together, or with a single list comprehension. | ||
|
||
.. activecode:: listcomp_9 | ||
|
||
things = [3, 4, 6, 7, 0, 1 | ||
#chaining together filter and map: | ||
# first, filter to keep only the even numbers | ||
# double each of them | ||
print map(lambda x: x*2, filter(lambda y: y % 2 == 0, things)) | ||
|
||
# equivalent version using list comprehension | ||
print [x*2 for x in things if x % 2 == 0] | ||
|
||
|
||
**Check your understanding** | ||
|
||
.. mchoicemf:: test_question9_20_1 | ||
:answer_a: [4,2,8,6,5] | ||
:answer_b: [8,4,16,12,10] | ||
:answer_c: 10 | ||
:answer_d: [10]. | ||
:correct: d | ||
:feedback_a: Items from alist are doubled before being placed in blist. | ||
:feedback_b: Not all the items in alist are to be included in blist. Look at the if clause. | ||
:feedback_c: The result needs to be a list. | ||
:feedback_d: Yes, 5 is the only odd number in alist. It is doubled before being placed in blist. | ||
|
||
What is printed by the following statements? | ||
|
||
.. code-block:: python | ||
alist = [4,2,8,6,5] | ||
blist = [num*2 for num in alist if num%2==1] | ||
print blist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.