VPython MapReduceFilter: Difference between revisions

From Physics Book
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
'''<big>Sabrina Yang - Spring 2026</big>'''


== '''Introduction''' ==
== '''Introduction''' ==


In Python, map, reduce, and filter are all different types of functions users can operate on sequences of elements. These functions help for making coding in VPython functional. All three of the functions take in a mathematical function and a sequence that should be run through the mathematical function.  
In Python, <code>map()</code>, <code>filter()</code>, and <code>reduce()</code> are
known as '''higher-order functions'''. Higher-order functions are functions that take other functions as arguments.
These functions are especially valuable.
A typical simulation can include hundreds of objects and variables that each operate under the same physics laws. Instead of writing
for loops to iterate through each object, <code>map()</code>, <code>filter()</code>,
and <code>reduce()</code> handles the iteration automatically, which makes the code shorter and more efficient.
 
The three functions each serve a its own role:
* <code>map()</code>: '''transforms''' every element in a list by applying a function to it
* <code>filter()</code>: '''selects''' a subset of elements that satisfy a condition
* <code>reduce()</code>: '''aggregates''' all elements into a single accumulated value
 
'''Important note for Python 3:''' <code>map()</code> and <code>filter()</code> return
lazy iterator objects, in other words objects that don't do any work until you ask it for the results, rather than lists. This means they do not compute anything until
you actually need the values. Wrap them in <code>list()</code> to force evaluation and
get a plain list back. <code>reduce()</code> was removed from Python 3's built-ins and
must be explicitly imported:
from functools import reduce
 
'''Important note for GlowScript VPython:''' GlowScript runs a restricted subset of
Python and does not support lambda expressions or the <code>functools</code> module.  
Use named <code>def</code> functions instead of lambdas, and implement
<code>reduce()</code> manually as shown in the interactive simulation section below.
 
----
 
== '''Background: Functional Programming''' ==
 
To fully understand <code>map()</code>, <code>filter()</code>, and <code>reduce()</code>,
you need to understand first-class functions. In Python, all functions
are first class objects, meaning they can be:
* Assigned to variables
* Passed as arguments to other functions
* Returned as values from other functions
 
This is what makes higher-order functions possible. When you write
<code>map(calc_weight, masses)</code>, you are passing the function
<code>calc_weight</code> itself as an argument to
<code>map()</code>. <code>map()</code> then calls <code>calc_weight</code>
for each element.
 
----
 
== '''Lambda Expressions''' ==
 
A '''lambda expression''' is a function you write in one line without giving it a name. The syntax is:
 
lambda <parameters>: <expression>
 
The function exists only at the point where
it is used. These two definitions produce the same results:
 
# Traditional way
def square(x):
    return x**2
# Using lambda
square = lambda x: x**2
 
Lambdas save you from having to define a whole separate function when you only need it once:
 
# Without lambda: requires a function defined somewhere else
result = list(map(square, [1, 2, 3, 4]))
# With lambda: no defined function needed
result = list(map(lambda x: x**2, [1, 2, 3, 4]))
# Result: [1, 4, 9, 16]
 
Lambda expressions can also take multiple parameters, which is useful for
<code>reduce()</code>:
 
from functools import reduce
total = reduce(lambda acc, x: acc + x, [1, 2, 3, 4], 0)
# Result: 10
 
'''When to use lambdas vs def:'''
* Use a lambda when the function is short, used only once, and  
passed directly as an argument
* Use <code>def</code> when the function is longer than one line or reused constantly
 
'''GlowScript limitation:''' Lambda expressions are not supported in GlowScript VPython.
Always use named <code>def</code> functions when writing code for Trinket or
GlowScript.


----
----


== '''Inputs and Type Matching''' ==


== '''Inputs''' ==
All three functions share the same basic calling convention:


map(), filter(), and reduce() take in two parameters. The first parameter is the function that the user would like to use. Typical functions include squaring a number, dividing a number, or creating some type of function that performs mathematical operations. The second parameter is the list the user would like to input into the function. If the function is mathematical, then a list of numbers is needed to be passed through. The types of the function must match the types of the list.
higher_order_function(function, iterable)
Example:
        def cubed(x): return x**3
        items = [1, 2, 3, 4]
        map(cubed, items)
As you can see here, the cubed function went in first, and then then items list came in next.
These functions also use lambdas which are used to make code shorter and replace having to making a function.


== '''Lambda Function''' ==
The '''function''' argument describes the operation to perform. The '''iterable'''
argument is the sequence of data to operate on, which can be a list, tuple, range,
or any other iterable Python object.


One important constraint is '''type matching''': the function must be able to accept
the types contained in the iterable. For example, if your list contains floating-point
numbers, your function must expect floats. Mismatches will cause a <code>TypeError</code>
at runtime.


The lambda function is used to replace the need to make a new function.
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 format is:
The same using a lambda:
      lambda x: condition.
items = [1, 2, 3, 4]
Lambda x is used in replacement of a function.
result = list(map(lambda x: x**3, items))
Instead of:
# Result: [1, 8, 27, 64]
      def cubed(x): return x**3
      items = [1,2,3]
      map(cubed, items)
a user can do:
      items = [1,2,3]
      map(lambda x: x**3, items)


You can also pass Python's built-in functions directly:
words = ['hello', 'world', 'vpython']
lengths = list(map(len, words))
# Result: [5, 5, 7]


----


== '''Map()''' ==
== '''Map()''' ==


Map() is a function used to apply a function that is passed in to a list of items that must have the function performed on each of the items.
=== How it works ===
The format is:
 
                      map(function, alist)
<code>map(function, iterable)</code> applies a function to '''every element''' of an
Each item in the list gets passed through the function, and a new list gets created with each item that had went through the function.
iterable and returns an iterator of the results. The original list is never modified. Instead,
Example:
a new sequence of transformed values is produced. The output always has the same number
        def timestwo(x): return x*2
of elements as the input.
        numlist = [1,2,3,4,5]
 
        map(timestwo, numlist)
map(function, iterable)
        # your result will be [2,4,6,8,10]
 
Map is extremely useful when someone would like to perform a certain action to each thing in their list. It helps short code because rather than performing the math function for each item on a new line, the code becomes shortened to a few lines.  
For a list <code>[a, b, c, d]</code> and a function <code>f</code>:
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]
 
=== Examples using Physics ===
 
'''Computing gravitational weight (F = mg) for a set of 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
 
'''Computing kinetic energy (KE = ½mv²) for a set of 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 a list of temperatures 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
 
=== Why use map() instead of a for-loop? ===
 
Both of the following produce the same result, but <code>map()</code> is shorter, and expresses the point more directly:
 
# For-loop approach
weights = []
for m in masses:
    weights.append(m * 9.8)
# map() approach — same result, fewer lines
weights = list(map(lambda m: m * 9.8, masses))


----


== '''Filter()''' ==
== '''Filter()''' ==


=== How it works ===
<code>filter(function, iterable)</code> keeps only the elements for which the function
returns <code>True</code>. The function must return a boolean value (or a value Python
treats as truthy or falsy). The output list may be shorter than the input list.
filter(function, iterable)
filter(lambda x: condition, iterable)


Filter is a function used to extract items from a list if they return true to the function given. It goes through a list and sees if the item in the list can be applied to the function. Lambdas are more commonly used when it comes to filter.
Conceptually, for a list <code>[a, b, c, d]</code> and a predicate function  
The format is:
<code>p</code>:
        filter(afunction, alist)
filter(p, [a, b, c, d]) →  [x for x in [a,b,c,d] if p(x) is True]
        filter(lambda x: condition, alist)
Here is an example:
        list = [3, 7, 5, 2, 1, 6]   
        filter(lambda x: x > 3, list)
        # this returns [7, 5, 6]
This is very useful because a for loop isn't needed to constantly check through each item in the list. Instead, filter shortens the amount of code needed to be written and finds the item that fit the condition. Iterations are then not needed.


=== Basic example ===
numbers = [3, 7, 5, 2, 1, 6]
result = list(filter(lambda x: x > 3, numbers))
# Result: [7, 5, 6]
=== Physics examples ===
'''Isolating particles moving above a speed threshold:'''
speeds = [120, 340, 95, 500, 210, 80]  # m/s
fast_particles = list(filter(lambda v: v > 200, speeds))
# Result: [340, 500, 210]
'''Keeping only positive charges from a mixed list:'''
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]
'''Filtering out particles that have left the simulation boundary:'''
# Each particle p has a .pos.x attribute representing its x position
boundary = 10.0  # meters
inside = list(filter(lambda p: abs(p.pos.x) < boundary, particles))
=== Passing None as the function ===
A special case: passing <code>None</code> instead of a function removes all
false values from the list (zeros, empty strings, <code>None</code>, <code>False</code>):
messy = [1, 0, 3, None, 5, 0, 7]
clean = list(filter(None, messy))
# Result: [1, 3, 5, 7]
----


== '''Reduce()''' ==
== '''Reduce()''' ==


=== How it works ===
<code>reduce(function, iterable, initializer)</code> '''cumulatively''' applies a
two-argument function to the elements of a list, reducing the entire sequence down
to a single scalar value.
The function passed to <code>reduce()</code> must accept exactly two arguments:
* The '''accumulator''' — the running result
* The '''current element''' — the next item from the list
After each call, the return value becomes the new accumulator for the next call.
from functools import reduce
reduce(function, iterable, initializer)
=== 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 all 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 maximum speed in a list of particles:'''
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
'''Computing total work done by forces over different displacements (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
=== Important warning ===


Reduce is a function used to pass the whole list into a function, and after one item is passed through, the result of it becomes the next thing that is put into the mathematical function.
Always provide an initializer (third argument) when using <code>reduce()</code>.
Calling it on an empty list without an initializer raises a <code>TypeError</code>.
With an initializer, an empty list returns the initializer value:


Example:
reduce(lambda acc, x: acc + x, [], 0.0)
              list = [1, 2, 3, 4]
# Returns 0.0 safely instead of raising an error
              reduce(lambda x, y: x*y)
              # The result is 24
              #Step 1: 1*2 = 2, the first element is x, and the second element is y
              #Step 2: 2*3 = 6, the result of step one is now x, and y the next element after that
              #Step 3: 6*4= 24
This function is useful if a person needs to pass numbers through and wants to use the new values again in the same function.


----


== '''Use In Physics''' ==
== '''Combining map(), filter(), and reduce()''' ==


These functions can be used in VPython for certain things. If a person would like to calculate the force of gravity on different objects, a person can make a list of masses and then multiply by 9.8.
The power of these functions come from chaining them together into a  
Example:
data pipeline. Each function's output becomes the next function's input, creating
        masslist = [1, 3, 5, 10, 20]
a clean sequence of transformation → selection → aggregation.
        map(lambda x: x*9.8, masslist)
This example allows for the whole lists of masses to find out their gravitational forces on earth.
These functions can make solving physics problems on multiple items easier instead of changing the value each time something new needs to be calculated.


'''Example — total kinetic energy of only the fast-moving particles in a system:'''


from functools import reduce
# Step 1: filter() — only keep particles with a speed greater than 3 m/s
moving = list(filter(lambda p: p.speed > 3.0, particles))
# Step 2: map() — calculate the kinetic energy for each particle
ke_list = list(map(lambda p: 0.5 * p.mass * p.speed**2, moving))
# Step 3: reduce() — add all the kinetic energies
total_ke = reduce(lambda acc, ke: acc + ke, ke_list, 0.0)
print("Total KE of fast particles:", round(total_ke, 2), "J")
This three-step pattern (filter, map, reduce) is one of the most widely used patterns in programming.
----
== '''Interactive Simulation''' ==
The following GlowScript simulation demonstrates all three functions working
together in a physics context:
[https://trinket.io/glowscript/9e53d57b352f map(), filter(), and reduce() in VPython Physics — Trinket]
The simulation creates five spheres arranged in a horizontal row, each assigned a
different mass (ranging from 1 to 8 kg) and a different speed (ranging from 1.5 to
6 m/s). The radius of each sphere is proportional to its mass.
The program then demonstrates each function in sequence:
* '''map()''' iterates over the list of masses and computes the gravitational weight
of each sphere using Newton's second law (F = mg, with g = 9.8 m/s²). The results
are printed to the console, showing the weight in Newtons for each sphere.
* '''filter()''' checks every sphere's speed and keeps only those moving faster than
3.0 m/s. Those spheres are turned '''red''' in the 3D scene, providing a visual
indicator of which objects meet the threshold condition. The speeds of the selected
spheres are also printed.
* '''reduce()''' — implemented manually as a custom function since GlowScript does
not support the <code>functools</code> module. It adds the kinetic energy of every sphere into a single total. The individual kinetic energies
and the system total are printed to the console.
Together, the simulation illustrates the filter → map → reduce pipeline in a
physical setting, showing how the three functions complement each other.
----


== '''References''' ==
== '''References''' ==
[http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php]
 
[http://book.pythontips.com/en/latest/map_filter.html]
[http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php 1. Python map, filter, reduce — bogotobogo.com]
[http://vpython.org/contents/docs/VisualIntro.html]
 
[http://book.pythontips.com/en/latest/map_filter.html 2. Map, Filter — Python Tips]
 
[http://vpython.org/contents/docs/VisualIntro.html 3. VPython Documentation — vpython.org]
 
[https://docs.python.org/3/library/functions.html 4. Python 3 Built-in Functions (map, filter) — Python Software Foundation]
 
[https://docs.python.org/3/library/functools.html 5. functools module (reduce) — Python Software Foundation]
 
[https://docs.python.org/3/howto/functional.html 6. Functional Programming HOWTO — Python Software Foundation]
 
[https://realpython.com/python-map-function/ 7. Python's map() — Real Python]
 
[https://realpython.com/python-filter-function/ 8. Python's filter() — Real Python]
 
[https://realpython.com/python-reduce-function/ 9. Python's reduce() — Real Python]
 
[https://realpython.com/python-lambda/ 10. Lambda Expressions in Python — Real Python]
 
[https://www.geeksforgeeks.org/functional-programming-in-python/ 11. Functional Programming in Python — GeeksforGeeks]
 
[https://www.geeksforgeeks.org/higher-order-functions-in-python/ 12. Higher-Order Functions in Python — GeeksforGeeks]
 
[https://www.glowscript.org 13. GlowScript VPython — Official Site]
 
[https://trinket.io/glowscript 14. GlowScript on Trinket]
 
[https://vpython.org 15. VPython Official Documentation]

Revision as of 19:13, 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. These functions are especially valuable. A typical simulation can include hundreds of objects and variables that each operate under the same physics laws. Instead of writing for loops to iterate through each object, map(), filter(), and reduce() handles the iteration automatically, which makes the code shorter and more efficient.

The three functions each serve a its own role:

  • map(): transforms every element in a list by applying a function to it
  • filter(): selects a subset of elements that satisfy a condition
  • reduce(): aggregates all elements into a single accumulated value

Important note for Python 3: map() and filter() return lazy iterator objects, in other words objects that don't do any work until you ask it for the results, rather than lists. This means they do not compute anything until you actually need the values. Wrap them in list() to force evaluation and get a plain list back. reduce() was removed from Python 3's built-ins and must be explicitly imported:

from functools import reduce

Important note for GlowScript VPython: GlowScript runs a restricted subset of Python and does not support lambda expressions or the functools module. Use named def functions instead of lambdas, and implement reduce() manually as shown in the interactive simulation section below.


Background: Functional Programming

To fully understand map(), filter(), and reduce(), you need to understand first-class functions. In Python, all functions are first class objects, meaning they can be:

  • Assigned to variables
  • Passed as arguments to other functions
  • Returned as values from other functions

This is what makes higher-order functions possible. When you write map(calc_weight, masses), you are passing the function calc_weight itself as an argument to map(). map() then calls calc_weight for each element.


Lambda Expressions

A lambda expression is a function you write in one line without giving it a name. The syntax is:

lambda <parameters>: <expression>

The function exists only at the point where it is used. These two definitions produce the same results:

# Traditional way
def square(x):
    return x**2

# Using lambda
square = lambda x: x**2

Lambdas save you from having to define a whole separate function when you only need it once:

# Without lambda: requires a function defined somewhere else
result = list(map(square, [1, 2, 3, 4]))

# With lambda: no defined function needed
result = list(map(lambda x: x**2, [1, 2, 3, 4]))
# Result: [1, 4, 9, 16]

Lambda expressions can also take multiple parameters, which is useful for reduce():

from functools import reduce
total = reduce(lambda acc, x: acc + x, [1, 2, 3, 4], 0)
# Result: 10

When to use lambdas vs def:

  • Use a lambda when the function is short, used only once, and

passed directly as an argument

  • Use def when the function is longer than one line or reused constantly

GlowScript limitation: Lambda expressions are not supported in GlowScript VPython. Always use named def functions when writing code for Trinket or GlowScript.


Inputs and Type Matching

All three functions share the same basic calling convention:

higher_order_function(function, iterable)

The function argument describes the operation to perform. The iterable argument is the sequence of data to operate on, which can be a list, tuple, range, or any other iterable Python object.

One important constraint is type matching: the function must be able to accept the types contained in the iterable. For example, if your list contains floating-point numbers, your function must expect floats. Mismatches will cause a TypeError at runtime.

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 using 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 directly:

words = ['hello', 'world', 'vpython']
lengths = list(map(len, words))
# Result: [5, 5, 7]

Map()

How it works

map(function, iterable) applies a function to every element of an iterable and returns an iterator of the results. The original list is never modified. Instead, a new sequence of transformed values is produced. The output always has the same number of elements as the input.

map(function, iterable)

For a list [a, b, c, d] and a 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]

Examples using Physics

Computing gravitational weight (F = mg) for a set of 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

Computing kinetic energy (KE = ½mv²) for a set of 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 a list of temperatures 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

Why use map() instead of a for-loop?

Both of the following produce the same result, but map() is shorter, and expresses the point more directly:

# For-loop approach
weights = []
for m in masses:
    weights.append(m * 9.8)

# map() approach — same result, fewer lines
weights = list(map(lambda m: m * 9.8, masses))

Filter()

How it works

filter(function, iterable) keeps only the elements for which the function returns True. The function must return a boolean value (or a value Python treats as truthy or falsy). The output list may be shorter than the input list.

filter(function, iterable)
filter(lambda x: condition, iterable)

Conceptually, for a list [a, b, c, d] and a predicate function p:

filter(p, [a, b, c, d])  →  [x for x in [a,b,c,d] if p(x) is True]

Basic example

numbers = [3, 7, 5, 2, 1, 6]
result = list(filter(lambda x: x > 3, numbers))
# Result: [7, 5, 6]

Physics examples

Isolating particles moving above a speed threshold:

speeds = [120, 340, 95, 500, 210, 80]  # m/s

fast_particles = list(filter(lambda v: v > 200, speeds))
# Result: [340, 500, 210]

Keeping only positive charges from a mixed list:

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]

Filtering out particles that have left the simulation boundary:

# Each particle p has a .pos.x attribute representing its x position
boundary = 10.0  # meters

inside = list(filter(lambda p: abs(p.pos.x) < boundary, particles))

Passing None as the function

A special case: passing None instead of a function removes all false values from the list (zeros, empty strings, None, False):

messy = [1, 0, 3, None, 5, 0, 7]
clean = list(filter(None, messy))
# Result: [1, 3, 5, 7]

Reduce()

How it works

reduce(function, iterable, initializer) cumulatively applies a two-argument function to the elements of a list, reducing the entire sequence down to a single scalar value.

The function passed to reduce() must accept exactly two arguments:

  • The accumulator — the running result
  • The current element — the next item from the list

After each call, the return value becomes the new accumulator for the next call.

from functools import reduce
reduce(function, iterable, initializer)

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 all 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 maximum speed in a list of particles:

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

Computing total work done by forces over different displacements (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

Important warning

Always provide an initializer (third argument) when using reduce(). Calling it on an empty list without an initializer raises a TypeError. With an initializer, an empty list returns the initializer value:

reduce(lambda acc, x: acc + x, [], 0.0)
# Returns 0.0 safely instead of raising an error

Combining map(), filter(), and reduce()

The power of these functions come from chaining them together into a data pipeline. Each function's output becomes the next function's input, creating a clean sequence of transformation → selection → aggregation.

Example — total kinetic energy of only the fast-moving particles in a system:

from functools import reduce

# Step 1: filter() — only keep particles with a speed greater than 3 m/s
moving = list(filter(lambda p: p.speed > 3.0, particles))

# Step 2: map() — calculate the kinetic energy for each particle
ke_list = list(map(lambda p: 0.5 * p.mass * p.speed**2, moving))

# Step 3: reduce() — add all the kinetic energies
total_ke = reduce(lambda acc, ke: acc + ke, ke_list, 0.0)
print("Total KE of fast particles:", round(total_ke, 2), "J")

This three-step pattern (filter, map, reduce) is one of the most widely used patterns in programming.



Interactive Simulation

The following GlowScript simulation demonstrates all three functions working together in a physics context: map(), filter(), and reduce() in VPython Physics — Trinket

The simulation creates five spheres arranged in a horizontal row, each assigned a different mass (ranging from 1 to 8 kg) and a different speed (ranging from 1.5 to 6 m/s). The radius of each sphere is proportional to its mass.

The program then demonstrates each function in sequence:

  • map() iterates over the list of masses and computes the gravitational weight

of each sphere using Newton's second law (F = mg, with g = 9.8 m/s²). The results are printed to the console, showing the weight in Newtons for each sphere.

  • filter() checks every sphere's speed and keeps only those moving faster than

3.0 m/s. Those spheres are turned red in the 3D scene, providing a visual indicator of which objects meet the threshold condition. The speeds of the selected spheres are also printed.

  • reduce() — implemented manually as a custom function since GlowScript does

not support the functools module. It adds the kinetic energy of every sphere into a single total. The individual kinetic energies and the system total are printed to the console.

Together, the simulation illustrates the filter → map → reduce pipeline in a physical setting, showing how the three functions complement each other.


References

1. Python map, filter, reduce — bogotobogo.com

2. Map, Filter — Python Tips

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

13. GlowScript VPython — Official Site

14. GlowScript on Trinket

15. VPython Official Documentation