VPython MapReduceFilter: Difference between revisions
Sabrinayang (talk | contribs) No edit summary |
Sabrinayang (talk | contribs) No edit summary |
||
| Line 4: | Line 4: | ||
In Python, <code>map()</code>, <code>filter()</code>, and <code>reduce()</code> are | In Python, <code>map()</code>, <code>filter()</code>, and <code>reduce()</code> are | ||
known as | known as higher-order functions. Higher-order functions are functions that | ||
take other functions as arguments. A typical VPython simulation can have hundreds of | |||
A typical simulation can | objects that all follow the same physics equations, and writing for-loops to do the same | ||
for loops to | calculation over and over can be inefficient. <code>map()</code>, | ||
and <code>reduce()</code> | <code>filter()</code>, and <code>reduce()</code> take care of the for-loops, | ||
allowing you to focus on the point of the code itself. | |||
Each function does something different: | |||
* <code>map()</code>: | * <code>map()</code>: applies a function to every element in a list | ||
* <code>filter()</code>: | * <code>filter()</code>: iterates through a list and only keeps the elements that meet a certain condition | ||
* <code>reduce()</code>: | * <code>reduce()</code>: takes a whole list and turns it into one single value | ||
''' | '''Python 3 note:''' <code>map()</code> and <code>filter()</code> do not actually work until you ask for the results. Wrap them in <code>list()</code> to get | ||
a list back. <code>reduce()</code> has to be imported before you can use it: | |||
from functools import reduce | from functools import reduce | ||
''' | '''GlowScript note:''' GlowScript does not support lambda expressions or the | ||
<code>functools</code> module. Use regular <code>def</code> functions instead of | |||
Use | lambdas, and write <code>reduce()</code> yourself. Here is an example of this | ||
<code>reduce()</code> | in the simulation section below. | ||
---- | ---- | ||
== '''Background | == '''Background''' == | ||
In Python, functions are objects just like numbers or strings. That means you can: | |||
* Store a function in a variable | |||
are | * Pass a function into another function as an argument | ||
* | * Get a function back as a return value | ||
* | |||
* | |||
This is what makes | This is what makes <code>map()</code>, <code>filter()</code>, and <code>reduce()</code> | ||
<code>map(calc_weight, masses)</code>, you are passing the function | work. When you write <code>map(calc_weight, masses)</code>, you are passing the | ||
<code>calc_weight</code> itself | function <code>calc_weight</code> itself into <code>map()</code>. Then | ||
<code>map()</code>. <code>map()</code> | <code>map()</code> runs it on every item in the list so you don't have to. | ||
There are a few reasons why writing code this way is efficient: | |||
* '''It is easy to read:''' You can look at the code and immediately tell what it | |||
is doing — like if you see "apply this formula to every mass" you just get it, | |||
no decoding required | |||
* '''Fewer bugs:''' Every time you write a for-loop you have to manually keep track of index | |||
variables, which is easy to make mistakes on. These functions | |||
handle the indices, so there is less room for errors. | |||
* '''You can chain them:''' The output of <code>map()</code> can go straight into | |||
<code>filter()</code> or <code>reduce()</code> without extra steps, which keeps | |||
the variables clean and short. | |||
---- | ---- | ||
| Line 48: | Line 54: | ||
== '''Lambda Expressions''' == | == '''Lambda Expressions''' == | ||
A '''lambda expression''' is a function you write in one line without giving it a name. The | A '''lambda expression''' is a function you write in one line without giving it a name. | ||
The format is: | |||
lambda <parameters>: <expression> | lambda <parameters>: <expression> | ||
The function exists | The function only exists at the point where it is used. These two do the exact same thing: | ||
it is used. These two | |||
# | # Regular way | ||
def square(x): | def square(x): | ||
return x**2 | return x**2 | ||
# | # Lambda way | ||
square = lambda x: x**2 | square = lambda x: x**2 | ||
Lambdas save you from having to define a whole separate function when you only need it once: | Lambdas save you from having to define a whole separate function when you only | ||
need it once: | |||
# Without lambda: | # Without lambda: needs a function defined somewhere else | ||
result = list(map(square, [1, 2, 3, 4])) | result = list(map(square, [1, 2, 3, 4])) | ||
# With lambda: no | # With lambda: no separate function needed | ||
result = list(map(lambda x: x**2, [1, 2, 3, 4])) | result = list(map(lambda x: x**2, [1, 2, 3, 4])) | ||
# Result: [1, 4, 9, 16] | # Result: [1, 4, 9, 16] | ||
They can also take two inputs, which comes up when using <code>reduce()</code>: | |||
<code>reduce()</code>: | |||
from functools import reduce | from functools import reduce | ||
| Line 78: | Line 84: | ||
# Result: 10 | # Result: 10 | ||
''' | '''Lambda vs def — when to use which:''' | ||
* Use a lambda when the function is short, | * Use a lambda when the function is short, only needed once, and passed right | ||
into another function | |||
* Use <code>def</code> when the function is longer | * Use <code>def</code> when the function is longer or used in multiple places | ||
'''GlowScript | '''GlowScript note:''' Lambdas do not work in GlowScript at all. Always use | ||
Always use | <code>def</code> when writing code for Trinket. | ||
---- | ---- | ||
| Line 91: | Line 96: | ||
== '''Inputs and Type Matching''' == | == '''Inputs and Type Matching''' == | ||
All three functions | All three functions follow the same basic structure: | ||
function_name(function, list) | |||
The | The first argument is the function you want to use. The second is the list of | ||
data you want to run it on, which can be a list, tuple, etc. | |||
One | One thing to watch out for: the function has to be able to work with any item | ||
is in the list. If your list has decimal numbers but your function expects | |||
numbers, | whole numbers, Python will throw an error. | ||
Example using a named function: | Example using a named function: | ||
| Line 112: | Line 115: | ||
# Result: [1, 8, 27, 64] | # Result: [1, 8, 27, 64] | ||
The same | The same thing with a lambda: | ||
items = [1, 2, 3, 4] | items = [1, 2, 3, 4] | ||
result = list(map(lambda x: x**3, items)) | result = list(map(lambda x: x**3, items)) | ||
# Result: [1, 8, 27, 64] | # Result: [1, 8, 27, 64] | ||
You can also pass Python's built-in functions | You can also pass Python's built-in functions straight in: | ||
words = ['hello', 'world', 'vpython'] | words = ['hello', 'world', 'vpython'] | ||
lengths = list(map(len, words)) | lengths = list(map(len, words)) | ||
| Line 128: | Line 131: | ||
=== How it works === | === How it works === | ||
<code>map(function, | <code>map(function, list)</code> runs a function on every single element in a list | ||
and gives you back all the results. The original list stays the same; you get a | |||
new list of updated values. | |||
map(function, | map(function, list) | ||
So for a list <code>[a, b, c, d]</code> and some function <code>f</code>: | |||
map(f, [a, b, c, d]) → [f(a), f(b), f(c), f(d)] | map(f, [a, b, c, d]) → [f(a), f(b), f(c), f(d)] | ||
| Line 144: | Line 146: | ||
# Result: [2, 4, 6, 8, 10] | # Result: [2, 4, 6, 8, 10] | ||
=== | === Physics examples === | ||
''' | '''Gravitational weight (F = mg) for the masses:''' | ||
g = 9.8 # m/s^2 | g = 9.8 # m/s^2 | ||
masses = [0.5, 1.0, 2.5, 5.0, 10.0] # kg | masses = [0.5, 1.0, 2.5, 5.0, 10.0] # kg | ||
| Line 153: | Line 155: | ||
# Result: [4.9, 9.8, 24.5, 49.0, 98.0] Newtons | # Result: [4.9, 9.8, 24.5, 49.0, 98.0] Newtons | ||
''' | '''Kinetic energy of the velocities:''' | ||
mass = 2.0 # kg | mass = 2.0 # kg | ||
velocities = [3.0, 5.5, 2.1, 8.0] # m/s | velocities = [3.0, 5.5, 2.1, 8.0] # m/s | ||
| Line 160: | Line 162: | ||
# Result: [9.0, 30.25, 4.41, 64.0] Joules | # Result: [9.0, 30.25, 4.41, 64.0] Joules | ||
'''Converting | '''Converting temperature from Celsius to Kelvin:''' | ||
temps_C = [0, 20, 37, 100, -273.15] | temps_C = [0, 20, 37, 100, -273.15] | ||
temps_K = list(map(lambda T: T + 273.15, temps_C)) | temps_K = list(map(lambda T: T + 273.15, temps_C)) | ||
# Result: [273.15, 293.15, 310.15, 373.15, 0.0] Kelvin | # Result: [273.15, 293.15, 310.15, 373.15, 0.0] Kelvin | ||
=== | === map() vs a for-loop === | ||
Both of | Both of these give the same answer, but <code>map()</code> is more concise: | ||
# For-loop | # For-loop | ||
weights = [] | weights = [] | ||
for m in masses: | for m in masses: | ||
weights.append(m * 9.8) | weights.append(m * 9.8) | ||
# map() | # map() — same thing in one line | ||
weights = list(map(lambda m: m * 9.8, masses)) | weights = list(map(lambda m: m * 9.8, masses)) | ||
| Line 183: | Line 185: | ||
=== How it works === | === How it works === | ||
<code>filter(function, | <code>filter(function, list)</code> iterates through a list and only keeps the elements | ||
returns <code>True</code>. | where the function returns <code>True</code>. | ||
filter(function, list) | |||
filter(lambda x: condition, list) | |||
filter( | |||
=== | === Example === | ||
numbers = [3, 7, 5, 2, 1, 6] | numbers = [3, 7, 5, 2, 1, 6] | ||
| Line 202: | Line 199: | ||
=== Physics examples === | === Physics examples === | ||
''' | '''Retrieving only the fastest particles:''' | ||
speeds = [120, 340, 95, 500, 210, 80] # m/s | speeds = [120, 340, 95, 500, 210, 80] # m/s | ||
| Line 208: | Line 205: | ||
# Result: [340, 500, 210] | # Result: [340, 500, 210] | ||
'''Keeping | '''Keeping the positive charges:''' | ||
charges = [-1.6e-19, 1.6e-19, -3.2e-19, 3.2e-19, 0, 1.6e-19] # Coulombs | charges = [-1.6e-19, 1.6e-19, -3.2e-19, 3.2e-19, 0, 1.6e-19] # Coulombs | ||
| Line 214: | Line 211: | ||
# Result: [1.6e-19, 3.2e-19, 1.6e-19] | # Result: [1.6e-19, 3.2e-19, 1.6e-19] | ||
''' | '''Removing particles that exited the simulation boundary:''' | ||
# Each particle p has a .pos.x | # Each particle p has a .pos.x value for its x position | ||
boundary = 10.0 # meters | boundary = 10.0 # meters | ||
| Line 222: | Line 219: | ||
=== Passing None as the function === | === Passing None as the function === | ||
If you pass <code>None</code> instead of a function, <code>filter()</code> removes | |||
every zero, empty string, <code>None</code>, and <code>False</code> from the list: | |||
messy = [1, 0, 3, None, 5, 0, 7] | messy = [1, 0, 3, None, 5, 0, 7] | ||
| Line 235: | Line 232: | ||
=== How it works === | === How it works === | ||
<code>reduce(function, | <code>reduce(function, list, starting value)</code> takes a whole list and returns one single value. Unlike <code>map()</code> | ||
and <code>filter()</code>, you do not get a list back — you get one number. | |||
The function | The function you pass in needs to take two inputs: | ||
* The | * The running total so far | ||
* The | * The next item in the list | ||
After each | After each step, the result becomes the new total for the next step. | ||
from functools import reduce | from functools import reduce | ||
reduce(function, | reduce(function, list, starting value) | ||
=== Step-by-step walkthrough === | === Step-by-step walkthrough === | ||
| Line 261: | Line 257: | ||
=== Physics examples === | === Physics examples === | ||
'''Adding all masses in a system:''' | '''Adding up all the masses in a system:''' | ||
from functools import reduce | from functools import reduce | ||
| Line 268: | Line 264: | ||
# Result: 10.0 kg | # Result: 10.0 kg | ||
'''Finding the | '''Finding the fastest particle in a list:''' | ||
from functools import reduce | from functools import reduce | ||
| Line 275: | Line 271: | ||
# Result: 9.4 m/s | # Result: 9.4 m/s | ||
''' | '''Total work done (W = F·d):''' | ||
from functools import reduce | from functools import reduce | ||
| Line 285: | Line 281: | ||
# Result: 20.0 + 37.5 + 15.0 + 20.0 = 92.5 Joules | # Result: 20.0 + 37.5 + 15.0 + 20.0 = 92.5 Joules | ||
=== | === Watch out === | ||
Always | Always give <code>reduce()</code> a starting value as the third argument. If the | ||
list is empty and there is no starting value, Python will crash. With a starting | |||
value, an empty list will give you that value back instead: | |||
reduce(lambda acc, x: acc + x, [], 0.0) | reduce(lambda acc, x: acc + x, [], 0.0) | ||
# Returns 0.0 safely | # Returns 0.0 safely | ||
---- | ---- | ||
| Line 298: | Line 294: | ||
== '''Combining map(), filter(), and reduce()''' == | == '''Combining map(), filter(), and reduce()''' == | ||
It is also efficient that functions can be chained together. | |||
'''Example | '''Example: kinetic energy''' | ||
from functools import reduce | from functools import reduce | ||
# Step 1: filter() — | # Step 1: filter() — drop all values below 3.0 m/s | ||
moving = list(filter(lambda p: p.speed > 3.0, particles)) | moving = list(filter(lambda p: p.speed > 3.0, particles)) | ||
# Step 2: map() — calculate | # Step 2: map() — calculate KE for each remaining particle | ||
ke_list = list(map(lambda p: 0.5 * p.mass * p.speed**2, moving)) | ke_list = list(map(lambda p: 0.5 * p.mass * p.speed**2, moving)) | ||
# Step 3: reduce() — add all | # Step 3: reduce() — add them all up | ||
total_ke = reduce(lambda acc, ke: acc + ke, ke_list, 0.0) | total_ke = reduce(lambda acc, ke: acc + ke, ke_list, 0.0) | ||
print("Total KE of fast particles:", round(total_ke, 2), "J") | print("Total KE of fast particles:", round(total_ke, 2), "J") | ||
This | This filter → map → reduce pattern shows up all the time in physics simulations. | ||
Pick a group of objects, apply a formula to each one, then get one final number | |||
out of it. That is basically what these three functions are built for. | |||
---- | ---- | ||
'''Gravitational potential energy at different heights:''' | |||
g = 9.8 # m/s^2 | |||
m = 2.0 # kg | |||
heights = [1.0, 5.0, 10.0, 20.0, 50.0] # meters | |||
pe_list = list(map(lambda h: m * g * h, heights)) | |||
# Result: [19.6, 98.0, 196.0, 392.0, 980.0] Joules | |||
'''Electric force on an electron at different distances from a charge (Coulomb's law):''' | |||
k = 8.99e9 # N·m^2/C^2 | |||
Q = 1.0e-6 # source charge, Coulombs | |||
r_list = [0.1, 0.2, 0.5, 1.0] # meters | |||
forces = list(map(lambda r: k * Q * 1.6e-19 / r**2, r_list)) | |||
---- | |||
== '''Interactive Simulation''' == | == '''Interactive Simulation''' == | ||
The following GlowScript simulation | The following GlowScript simulation shows all three functions working together | ||
in a real physics example: | |||
[https://trinket.io/glowscript/9e53d57b352f map(), filter(), and reduce() in VPython Physics — Trinket] | [https://trinket.io/glowscript/9e53d57b352f map(), filter(), and reduce() in VPython Physics — Trinket] | ||
The simulation | The simulation puts five spheres in a row, each with a different mass between | ||
different mass | 1 and 8 kg and a different speed between 1.5 and 6 m/s. The size of each sphere | ||
6 m/s | matches its mass so you can see the difference right away. | ||
* '''map()''' | * '''map()''' goes through every mass and calculates the weight using F = mg. | ||
The weight of each sphere gets printed to the console. | |||
* '''filter()''' checks | * '''filter()''' checks each sphere's speed and keeps the ones faster | ||
3.0 m/s | than 3.0 m/s. | ||
* '''reduce()''' | * '''reduce()''' is written by hand since GlowScript does not have the | ||
not | <code>functools</code> module. It adds up the kinetic energy of every sphere | ||
one by one until it has one total number for the whole system, which then | |||
gets printed. | |||
This simulation is an accurate visualization of how all three functions work together. | |||
---- | ---- | ||
Revision as of 20:24, 26 April 2026
Sabrina Yang - Spring 2026
Introduction
In Python, map(), filter(), and reduce() are
known as higher-order functions. Higher-order functions are functions that
take other functions as arguments. A typical VPython simulation can have hundreds of
objects that all follow the same physics equations, and writing for-loops to do the same
calculation over and over can be inefficient. map(),
filter(), and reduce() take care of the for-loops,
allowing you to focus on the point of the code itself.
Each function does something different:
map(): applies a function to every element in a listfilter(): iterates through a list and only keeps the elements that meet a certain conditionreduce(): takes a whole list and turns it into one single value
Python 3 note: map() and filter() do not actually work until you ask for the results. Wrap them in list() to get
a list back. reduce() has to be imported before you can use it:
from functools import reduce
GlowScript note: GlowScript does not support lambda expressions or the
functools module. Use regular def functions instead of
lambdas, and write reduce() yourself. Here is an example of this
in the simulation section below.
Background
In Python, functions are objects just like numbers or strings. That means you can:
- Store a function in a variable
- Pass a function into another function as an argument
- Get a function back as a return value
This is what makes map(), filter(), and reduce()
work. When you write map(calc_weight, masses), you are passing the
function calc_weight itself into map(). Then
map() runs it on every item in the list so you don't have to.
There are a few reasons why writing code this way is efficient:
- It is easy to read: You can look at the code and immediately tell what it
is doing — like if you see "apply this formula to every mass" you just get it, no decoding required
- Fewer bugs: Every time you write a for-loop you have to manually keep track of index
variables, which is easy to make mistakes on. These functions handle the indices, so there is less room for errors.
- You can chain them: The output of
map()can go straight into
filter() or reduce() without extra steps, which keeps
the variables clean and short.
Lambda Expressions
A lambda expression is a function you write in one line without giving it a name. The format is:
lambda <parameters>: <expression>
The function only exists at the point where it is used. These two do the exact same thing:
# Regular way
def square(x):
return x**2
# Lambda way
square = lambda x: x**2
Lambdas save you from having to define a whole separate function when you only need it once:
# Without lambda: needs a function defined somewhere else result = list(map(square, [1, 2, 3, 4])) # With lambda: no separate function needed result = list(map(lambda x: x**2, [1, 2, 3, 4])) # Result: [1, 4, 9, 16]
They can also take two inputs, which comes up when using reduce():
from functools import reduce total = reduce(lambda acc, x: acc + x, [1, 2, 3, 4], 0) # Result: 10
Lambda vs def — when to use which:
- Use a lambda when the function is short, only needed once, and passed right
into another function
- Use
defwhen the function is longer or used in multiple places
GlowScript note: Lambdas do not work in GlowScript at all. Always use
def when writing code for Trinket.
Inputs and Type Matching
All three functions follow the same basic structure:
function_name(function, list)
The first argument is the function you want to use. The second is the list of data you want to run it on, which can be a list, tuple, etc.
One thing to watch out for: the function has to be able to work with any item is in the list. If your list has decimal numbers but your function expects whole numbers, Python will throw an error.
Example using a named function:
def cubed(x):
return x**3
items = [1, 2, 3, 4]
result = list(map(cubed, items))
# Result: [1, 8, 27, 64]
The same thing with a lambda:
items = [1, 2, 3, 4] result = list(map(lambda x: x**3, items)) # Result: [1, 8, 27, 64]
You can also pass Python's built-in functions straight in:
words = ['hello', 'world', 'vpython'] lengths = list(map(len, words)) # Result: [5, 5, 7]
Map()
How it works
map(function, list) runs a function on every single element in a list
and gives you back all the results. The original list stays the same; you get a
new list of updated values.
map(function, list)
So for a list [a, b, c, d] and some function f:
map(f, [a, b, c, d]) → [f(a), f(b), f(c), f(d)]
Basic example
numlist = [1, 2, 3, 4, 5] result = list(map(lambda x: x * 2, numlist)) # Result: [2, 4, 6, 8, 10]
Physics examples
Gravitational weight (F = mg) for the masses:
g = 9.8 # m/s^2 masses = [0.5, 1.0, 2.5, 5.0, 10.0] # kg weights = list(map(lambda m: m * g, masses)) # Result: [4.9, 9.8, 24.5, 49.0, 98.0] Newtons
Kinetic energy of the velocities:
mass = 2.0 # kg velocities = [3.0, 5.5, 2.1, 8.0] # m/s ke_list = list(map(lambda v: 0.5 * mass * v**2, velocities)) # Result: [9.0, 30.25, 4.41, 64.0] Joules
Converting temperature from Celsius to Kelvin:
temps_C = [0, 20, 37, 100, -273.15] temps_K = list(map(lambda T: T + 273.15, temps_C)) # Result: [273.15, 293.15, 310.15, 373.15, 0.0] Kelvin
map() vs a for-loop
Both of these give the same answer, but map() is more concise:
# For-loop
weights = []
for m in masses:
weights.append(m * 9.8)
# map() — same thing in one line
weights = list(map(lambda m: m * 9.8, masses))
Filter()
How it works
filter(function, list) iterates through a list and only keeps the elements
where the function returns True.
filter(function, list) filter(lambda x: condition, list)
Example
numbers = [3, 7, 5, 2, 1, 6] result = list(filter(lambda x: x > 3, numbers)) # Result: [7, 5, 6]
Physics examples
Retrieving only the fastest particles:
speeds = [120, 340, 95, 500, 210, 80] # m/s fast_particles = list(filter(lambda v: v > 200, speeds)) # Result: [340, 500, 210]
Keeping the positive charges:
charges = [-1.6e-19, 1.6e-19, -3.2e-19, 3.2e-19, 0, 1.6e-19] # Coulombs positive = list(filter(lambda q: q > 0, charges)) # Result: [1.6e-19, 3.2e-19, 1.6e-19]
Removing particles that exited the simulation boundary:
# Each particle p has a .pos.x value for its x position boundary = 10.0 # meters inside = list(filter(lambda p: abs(p.pos.x) < boundary, particles))
Passing None as the function
If you pass None instead of a function, filter() removes
every zero, empty string, None, and False from the list:
messy = [1, 0, 3, None, 5, 0, 7] clean = list(filter(None, messy)) # Result: [1, 3, 5, 7]
Reduce()
How it works
reduce(function, list, starting value) takes a whole list and returns one single value. Unlike map()
and filter(), you do not get a list back — you get one number.
The function you pass in needs to take two inputs:
- The running total so far
- The next item in the list
After each step, the result becomes the new total for the next step.
from functools import reduce reduce(function, list, starting value)
Step-by-step walkthrough
from functools import reduce numbers = [1, 2, 3, 4] result = reduce(lambda x, y: x * y, numbers) # Step 1: x=1, y=2 → 1 * 2 = 2 # Step 2: x=2, y=3 → 2 * 3 = 6 # Step 3: x=6, y=4 → 6 * 4 = 24 # Final result: 24
Physics examples
Adding up all the masses in a system:
from functools import reduce masses = [1.0, 2.0, 3.0, 4.0] # kg total_mass = reduce(lambda acc, m: acc + m, masses, 0.0) # Result: 10.0 kg
Finding the fastest particle in a list:
from functools import reduce speeds = [3.2, 7.8, 1.1, 9.4, 5.5] # m/s max_speed = reduce(lambda a, b: a if a > b else b, speeds) # Result: 9.4 m/s
Total work done (W = F·d):
from functools import reduce forces = [10.0, 25.0, 5.0, 40.0] # Newtons displacements = [2.0, 1.5, 3.0, 0.5] # meters work_list = list(map(lambda fd: fd[0] * fd[1], zip(forces, displacements))) total_work = reduce(lambda acc, w: acc + w, work_list, 0.0) # Result: 20.0 + 37.5 + 15.0 + 20.0 = 92.5 Joules
Watch out
Always give reduce() a starting value as the third argument. If the
list is empty and there is no starting value, Python will crash. With a starting
value, an empty list will give you that value back instead:
reduce(lambda acc, x: acc + x, [], 0.0) # Returns 0.0 safely
Combining map(), filter(), and reduce()
It is also efficient that functions can be chained together.
Example: kinetic energy
from functools import reduce
# Step 1: filter() — drop all values below 3.0 m/s
moving = list(filter(lambda p: p.speed > 3.0, particles))
# Step 2: map() — calculate KE for each remaining particle
ke_list = list(map(lambda p: 0.5 * p.mass * p.speed**2, moving))
# Step 3: reduce() — add them all up
total_ke = reduce(lambda acc, ke: acc + ke, ke_list, 0.0)
print("Total KE of fast particles:", round(total_ke, 2), "J")
This filter → map → reduce pattern shows up all the time in physics simulations. Pick a group of objects, apply a formula to each one, then get one final number out of it. That is basically what these three functions are built for.
Gravitational potential energy at different heights:
g = 9.8 # m/s^2 m = 2.0 # kg heights = [1.0, 5.0, 10.0, 20.0, 50.0] # meters pe_list = list(map(lambda h: m * g * h, heights)) # Result: [19.6, 98.0, 196.0, 392.0, 980.0] Joules
Electric force on an electron at different distances from a charge (Coulomb's law):
k = 8.99e9 # N·m^2/C^2 Q = 1.0e-6 # source charge, Coulombs r_list = [0.1, 0.2, 0.5, 1.0] # meters forces = list(map(lambda r: k * Q * 1.6e-19 / r**2, r_list))
Interactive Simulation
The following GlowScript simulation shows all three functions working together in a real physics example: map(), filter(), and reduce() in VPython Physics — Trinket
The simulation puts five spheres in a row, each with a different mass between 1 and 8 kg and a different speed between 1.5 and 6 m/s. The size of each sphere matches its mass so you can see the difference right away.
- map() goes through every mass and calculates the weight using F = mg.
The weight of each sphere gets printed to the console.
- filter() checks each sphere's speed and keeps the ones faster
than 3.0 m/s.
- reduce() is written by hand since GlowScript does not have the
functools module. It adds up the kinetic energy of every sphere
one by one until it has one total number for the whole system, which then
gets printed.
This simulation is an accurate visualization of how all three functions work together.
References
1. Python map, filter, reduce — bogotobogo.com
3. VPython Documentation — vpython.org
4. Python 3 Built-in Functions (map, filter) — Python Software Foundation
5. functools module (reduce) — Python Software Foundation
6. Functional Programming HOWTO — Python Software Foundation
7. Python's map() — Real Python
8. Python's filter() — Real Python
9. Python's reduce() — Real Python
10. Lambda Expressions in Python — Real Python
11. Functional Programming in Python — GeeksforGeeks
12. Higher-Order Functions in Python — GeeksforGeeks