Skip to main content

Explain Python Map, Filter and Reduce functions on a Iterable List, etc

 The map() and filter() functions are built-in Python functions that operate on iterables (like lists, tuples) and return iterators. They are often used for functional programming paradigms. Reduce summarizes - by cumulating values to a single item. 

  • map()Applies a given function to each item in an iterable and returns an iterator of the results.
Python
    def square(x):        return x * x        numbers = [1, 2, 3, 4, 5]    squared_numbers = map(square, numbers)    print(list(squared_numbers)) # Output: [1, 4, 9, 16, 25]
  • filter()Creates an iterator of elements from an iterable for which a function returns TrueIt essentially filters the iterable based on a condition. 
Python
    def is_even(x):        return x % 2 == 0        numbers = [1, 2, 3, 4, 5, 6]    even_numbers = filter(is_even, numbers)    print(list(even_numbers)) # Output: [2, 4, 6]
Both map() and filter() return iterators, which means their results are generated on demand. To get a list or tuple, you can use list() or tuple() to convert the iterator.

Python’s map() and filter() Explained: Supercharge Your Iterables
For Python Beginners and Beyond

Python’s map() and filter() are powerful built-in functions for transforming and filtering data in iterables (like lists, tuples, or sets). Let’s break down how they work, when to use them, and how they compare to alternatives like list comprehensions.


1. The map() Function

What it does:
Applies a function to every item in an iterable and returns a new iterator with the results.

Syntax:

python
Copy
map(function, iterable)  

Example:

python
Copy
# Double each number in a list  
numbers = [1, 2, 3, 4]  

# Using map with a lambda function  
doubled = map(lambda x: x * 2, numbers)  
print(list(doubled))  # Output: [2, 4, 6, 8]  

# Using map with a named function  
def add_five(n):  
    return n + 5  

result = map(add_five, numbers)  
print(list(result))  # Output: [6, 7, 8, 9]  

Key Points:

  • Returns an iterator (use list() to convert it to a list).

  • Works with any iterable (lists, tuples, etc.).

  • Great for element-wise transformations.


2. The filter() Function

What it does:
Filters items from an iterable based on a condition. Only items where the function returns True are kept.

Syntax:

python
Copy
filter(function, iterable)  

Example:

python
Copy
# Filter even numbers from a list  
numbers = [1, 2, 3, 4, 5, 6]  

# Using filter with a lambda  
evens = filter(lambda x: x % 2 == 0, numbers)  
print(list(evens))  # Output: [2, 4, 6]  

# Using filter with a named function  
def is_positive(n):  
    return n > 0  

mixed = [-5, 10, 0, -3, 7]  
positives = filter(is_positive, mixed)  
print(list(positives))  # Output: [10, 7]  

Key Points:

  • Returns an iterator (convert with list() for readability).

  • The function must return a boolean (True/False).

  • Ideal for selecting subsets of data based on conditions.


Combining map() and filter()

Chain them to transform and filter data:

python
Copy
# Square only the even numbers in a list  
numbers = [1, 2, 3, 4, 5]  

processed = map(  
    lambda x: x ** 2,  
    filter(lambda x: x % 2 == 0, numbers)  
)  

print(list(processed))  # Output: [4, 16]  

map()/filter() vs. List Comprehensions

Both achieve similar results, but list comprehensions are often more readable:

Using map() + filter():

python
Copy
result = map(lambda x: x * 2, filter(lambda x: x > 2, numbers))  

Equivalent list comprehension:

python
Copy
result = [x * 2 for x in numbers if x > 2]  

Pros of comprehensions:

  • More concise and Pythonic.

  • Easier to read for simple operations.

Pros of map()/filter():

  • Better for functional programming styles.

  • Can improve readability when using predefined functions.


When to Use Which?

  • map(): Use when applying a transformation to every item in an iterable.

  • filter(): Use when selecting items that meet a condition.

  • Comprehensions: Use for simpler logic (combine for and if in one line).

  • Functional Chains: Use map() + filter() for complex pipelines.


Key Takeaways

  • map() transforms data.

  • filter() selects data.

  • Both return iterators—convert to lists to see results.

  • Comprehensions are often simpler, but map()/filter() shine in functional code.


Try It Yourself!

python
Copy
# Challenge: Use map() and filter() to convert ["apple", "Banana", "CHERRY"] to uppercase and keep words with >5 letters.  
words = ["apple", "Banana", "CHERRY"]  

# Your code here!  


The reduce() Function

Python’s reduce() Function: Mastering Aggregation Tasks
For Intermediate Python Developers

The reduce() function is a powerful tool for aggregating data in Python, allowing you to iteratively apply a function to an iterable and "reduce" it to a single value. Let’s dive into how it works, when to use it, and how it compares to loops or built-in functions like sum().


What is reduce()?

  • Purpose: Applies a function cumulatively to items in an iterable, combining them into a single result.

  • Syntax:

    python
    Copy
    from functools import reduce  
    reduce(function, iterable[, initializer])  
    • function: A function that takes two arguments (the accumulated value and the next item).

    • iterable: A list, tuple, or other iterable.

    • initializer (optional): Starting value for the accumulation.


How It Works

  1. Takes the first two items from the iterable, applies the function to them.

  2. Uses the result as the new accumulated value.

  3. Repeats until all items are processed, returning a single output.


Examples

1. Summing Numbers

python
Copy
from functools import reduce  

numbers = [1, 2, 3, 4]  
sum_result = reduce(lambda acc, x: acc + x, numbers)  
print(sum_result)  # Output: 10  

2. Finding the Maximum Value

python
Copy
numbers = [5, 2, 9, 3]  
max_value = reduce(lambda a, b: a if a > b else b, numbers)  
print(max_value)  # Output: 9  

3. Flattening a List of Lists

python
Copy
lists = [[1, 2], [3, 4], [5, 6]]  
flattened = reduce(lambda acc, lst: acc + lst, lists, [])  
print(flattened)  # Output: [1, 2, 3, 4, 5, 6]  

4. Using an Initializer

python
Copy
# Multiply all numbers, starting with an initial value of 10  
numbers = [2, 3, 4]  
product = reduce(lambda acc, x: acc * x, numbers, 10)  
print(product)  # Output: 240 (10 * 2 * 3 * 4)  

Key Differences from Loops or Built-ins

ApproachProsCons
reduce()Concise, functional style.Less readable for complex logic.
for LoopExplicit control flow.More verbose.
Built-ins (e.g., sum())Optimized and readable.Limited to predefined operations.

When to Use reduce()

  • Custom Aggregation: When no built-in function exists (e.g., custom product logic).

  • Functional Programming: Chaining transformations with map()/filter().

  • Initializers: Needing a starting value (e.g., accumulating into a dictionary).


Pitfalls to Avoid

  1. Empty Iterables: Always use an initializer if the iterable might be empty.

    python
    Copy
    # Without initializer: Throws TypeError if list is empty!  
    reduce(lambda a, b: a + b, [], 0)  # Safe with initializer 0  
  2. Complex Logic: Use loops if the function becomes hard to read.


Alternatives to reduce()

  • Built-ins: Use sum()max(), or min() for simple tasks.

  • List Comprehensions: For intermediate aggregation steps.

  • Pandas/Numpy: For large datasets (e.g., df.sum() or np.prod()).


Key Takeaways

  • reduce() is ideal for custom cumulative operations.

  • Prefer built-ins like sum() for readability when possible.

  • Always handle empty iterables with an initializer.


Try It Yourself!

python
Copy
# Challenge: Use reduce() to count occurrences of words in a list.  
words = ["apple", "banana", "apple", "cherry", "banana"]  

# Expected output: {"apple": 2, "banana": 2, "cherry": 1}  

More

Map, Filter, Reduce


Tutorial

Map, Filter, and Reduce are paradigms of functional programming. They allow the programmer (you) to write simpler, shorter code, without neccessarily needing to bother about intricacies like loops and branching.

Essentially, these three functions allow you to apply a function across a number of iterables, in one fell swoop. map and filter come built-in with Python (in the __builtins__ module) and require no importing. reduce, however, needs to be imported as it resides in the functools module. Let's get a better understanding of how they all work, starting with map.

Map

The map() function in python has the following syntax:

map(func, *iterables)

Where func is the function on which each element in iterables (as many as they are) would be applied on. Notice the asterisk(*) on iterables? It means there can be as many iterables as possible, in so far func has that exact number as required input arguments. Before we move on to an example, it's important that you note the following:

  1. In Python 2, the map() function returns a list. In Python 3, however, the function returns a map object which is a generator object. To get the result as a list, the built-in list() function can be called on the map object. i.e. list(map(func, *iterables))
  2. The number of arguments to func must be the number of iterables listed.

Let's see how these rules play out with the following examples.

Say I have a list (iterable) of my favourite pet names, all in lower case and I need them in uppercase. Traditonally, in normal pythoning, I would do something like this:

  • script.py
    1
    2
    3
    4
    5
    6
    7
    8
    my_pets = ['alfred', 'tabitha', 'william', 'arla']
    uppered_pets = []
    for pet in my_pets:
    pet_ = pet.upper()
    uppered_pets.append(pet_)
    print(uppered_pets)
    • IPython Shell
      In [1]:

      Which would then output ['ALFRED', 'TABITHA', 'WILLIAM', 'ARLA']


      With map() functions, it's not only easier, but it's also much more flexible. I simply do this:

      • script.py
        1
        2
        3
        4
        5
        6
        # Python 3
        my_pets = ['alfred', 'tabitha', 'william', 'arla']
        uppered_pets = list(map(str.upper, my_pets))
        print(uppered_pets)
        • IPython Shell
          In [1]:

          Which would also output the same result. Note that using the defined map() syntax above, func in this case is str.upper and iterables is the my_pets list -- just one iterable. Also note that we did not call the str.upper function (doing this: str.upper()), as the map function does that for us on each element in the my_pets list.

          What's more important to note is that the str.upper function requires only one argument by definition and so we passed just one iterable to it. So, if the function you're passing requires two, or three, or n arguments, then you need to pass in two, three or n iterables to it. Let me clarify this with another example.

          Say I have a list of circle areas that I calculated somewhere, all in five decimal places. And I need to round each element in the list up to its position decimal places, meaning that I have to round up the first element in the list to one decimal place, the second element in the list to two decimal places, the third element in the list to three decimal places, etc. With map() this is a piece of cake. Let's see how.

          Python already blesses us with the round() built-in function that takes two arguments -- the number to round up and the number of decimal places to round the number up to. So, since the function requires two arguments, we need to pass in two iterables.

          • script.py
            1
            2
            3
            4
            5
            6
            7
            # Python 3
            circle_areas = [3.56773, 5.57668, 4.00914, 56.24241
            , 9.01344, 32.00013]
            result = list(map(round, circle_areas, range(1, 7
            )))
            print(result)
            • IPython Shell
              In [1]:

              See the beauty of map()? Can you imagine the flexibility this evokes?

              The range(1, 7) function acts as the second argument to the round function (the number of required decimal places per iteration). So as map iterates through circle_areas, during the first iteration, the first element of circle_areas3.56773 is passed along with the first element of range(1,7)1 to round, making it effectively become round(3.56773, 1). During the second iteration, the second element of circle_areas5.57668 along with the second element of range(1,7)2 is passed to round making it translate to round(5.57668, 2). This happens until the end of the circle_areas list is reached.

              I'm sure you're wondering: "What if I pass in an iterable less than or more than the length of the first iterable? That is, what if I pass range(1, 3) or range(1, 9999) as the second iterable in the above function". And the answer is simple: nothing! Okay, that's not true. "Nothing" happens in the sense that the map() function will not raise any exception, it will simply iterate over the elements until it can't find a second argument to the function, at which point it simply stops and returns the result.

              So, for example, if you evaluate result = list(map(round, circle_areas, range(1, 3))), you won't get any error even as the length of circle_areas and the length of range(1, 3) differ. Instead, this is what Python does: It takes the first element of circle_areas and the first element of range(1,3) and passes it to roundround evaluates it then saves the result. Then it goes on to the second iteration, second element of circle_areas and second element of range(1,3)round saves it again. Now, in the third iteration (circle_areas has a third element), Python takes the third element of circle_areas and then tries to take the third element of range(1,3) but since range(1,3) does not have a third element, Python simply stops and returns the result, which in this case would simply be [3.6, 5.58].

              Go ahead, try it.

              • script.py
                1
                2
                3
                4
                5
                6
                7
                # Python 3
                circle_areas = [3.56773, 5.57668, 4.00914, 56.24241
                , 9.01344, 32.00013]
                result = list(map(round, circle_areas, range(1, 3
                )))
                print(result)
                • IPython Shell
                  In [1]:

                  The same thing happens if circle_areas is less than the length of the second iterable. Python simply stops when it can't find the next element in one of the iterables.


                  To consolidate our knowledge of the map() function, we are going to use it to implement our own custom zip() function. The zip() function is a function that takes a number of iterables and then creates a tuple containing each of the elements in the iterables. Like map(), in Python 3, it returns a generator object, which can be easily converted to a list by calling the built-in list function on it. Use the below interpreter session to get a grip of zip() before we create ours with map()

                  • script.py
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    # Python 3
                    my_strings = ['a', 'b', 'c', 'd', 'e']
                    my_numbers = [1, 2, 3, 4, 5]
                    results = list(zip(my_strings, my_numbers))
                    print(results)
                    • IPython Shell
                      In [1]:

                      As a bonus, can you guess what would happen in the above session if my_strings and my_numbers are not of the same length? No? try it! Change the length of one of them.


                      Onto our own custom zip() function!

                      • script.py
                        1
                        2
                        3
                        4
                        5
                        6
                        7
                        8
                        # Python 3
                        my_strings = ['a', 'b', 'c', 'd', 'e']
                        my_numbers = [1, 2, 3, 4, 5]
                        results = list(map(lambda x, y: (x, y), my_strings,
                        my_numbers))
                        print(results)
                        • IPython Shell
                          In [1]:

                          Did you also notice that I didn't even need to create a function using the def my_function() standard way? That's how flexible map(), and Python in general, is! I simply used a lambda function. This is not to say that using the standard function definition method (of def function_name()) isn't allowed, it still is. I simply preferred to write less code (be "Pythonic").

                          That's all about map. Onto filter()

                          Filter

                          While map() passes each element in the iterable through a function and returns the result of all elements having passed through the function, filter(), first of all, requires the function to return boolean values (true or false) and then passes each element in the iterable through the function, "filtering" away those that are false. It has the following syntax:

                          filter(func, iterable)

                          The following points are to be noted regarding filter():

                          1. Unlike map(), only one iterable is required.
                          2. The func argument is required to return a boolean type. If it doesn't, filter simply returns the iterable passed to it. Also, as only one iterable is required, it's implicit that func must only take one argument.
                          3. filter passes each element in the iterable through func and returns only the ones that evaluate to true. I mean, it's right there in the name -- a "filter".

                          Let's see some examples

                          The following is a list (iterable) of the scores of 10 students in a Chemistry exam. Let's filter out those who passed with scores more than 75...using filter.

                          • script.py
                            1
                            2
                            3
                            4
                            5
                            6
                            7
                            8
                            9
                            # Python 3
                            scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65]
                            def is_A_student(score):
                            return score > 75
                            over_75 = list(filter(is_A_student, scores))
                            print(over_75)
                            • IPython Shell
                              In [1]:

                              The next example will be a palindrome detector. A "palindrome" is a word, phrase, or sequence that reads the same backwards as forwards. Let's filter out words that are palindromes from a tuple (iterable) of suspected palindromes.

                              • script.py
                                1
                                2
                                3
                                4
                                5
                                6
                                # Python 3
                                dromes = ("demigod", "rewire", "madam", "freer",
                                "anutforajaroftuna", "kiosk")
                                palindromes = list(filter(lambda word: word ==
                                word[::-1], dromes))
                                print(palindromes)
                                • IPython Shell
                                  In [1]:

                                  Which should output ['madam', 'anutforajaroftuna'].

                                  Reduce

                                  reduce applies a function of two arguments cumulatively to the elements of an iterable, optionally starting with an initial argument. It has the following syntax:

                                  reduce(func, iterable[, initial])

                                  Where func is the function on which each element in the iterable gets cumulatively applied to, and initial is the optional value that gets placed before the elements of the iterable in the calculation, and serves as a default when the iterable is empty. The following should be noted about reduce(): 1. func requires two arguments, the first of which is the first element in iterable (if initial is not supplied) and the second element in iterable. If initial is supplied, then it becomes the first argument to func and the first element in iterable becomes the second element. 2. reduce "reduces" (I know, forgive me) iterable into a single value.

                                  As usual, let's see some examples.

                                  Let's create our own version of Python's built-in sum() function. The sum() function returns the sum of all the items in the iterable passed to it.

                                  • script.py
                                    1
                                    2
                                    3
                                    4
                                    5
                                    6
                                    7
                                    8
                                    9
                                    10
                                    # Python 3
                                    from functools import reduce
                                    numbers = [3, 4, 6, 9, 34, 12]
                                    def custom_sum(first, second):
                                    return first + second
                                    result = reduce(custom_sum, numbers)
                                    print(result)
                                    • IPython Shell
                                      In [1]:

                                      The result, as you'll expect is 68.

                                      So, what happened?

                                      As usual, it's all about iterations: reduce takes the first and second elements in numbers and passes them to custom_sum respectively. custom_sum computes their sum and returns it to reducereduce then takes that result and applies it as the first element to custom_sum and takes the next element (third) in numbers as the second element to custom_sum. It does this continuously (cumulatively) until numbers is exhausted.

                                      Let's see what happens when I use the optional initial value.

                                      • script.py
                                        1
                                        2
                                        3
                                        4
                                        5
                                        6
                                        7
                                        8
                                        9
                                        10
                                        # Python 3
                                        from functools import reduce
                                        numbers = [3, 4, 6, 9, 34, 12]
                                        def custom_sum(first, second):
                                        return first + second
                                        result = reduce(custom_sum, numbers, 10)
                                        print(result)
                                        • IPython Shell
                                          In [1]:

                                          The result, as you'll expect, is 78 because reduce, initially, uses 10 as the first argument to custom_sum.

                                          That's all about Python's Map, Reduce, and Filter. Try on the below exercises to help ascertain your understanding of each function.


                                          Comments

                                          Popular posts from this blog

                                          Simple Linear Regression - and Related Regression Loss Functions

                                          Today's Topics: a. Regression Algorithms  b. Outliers - Explained in Simple Terms c. Common Regression Metrics Explained d. Overfitting and Underfitting e. How are Linear and Non Linear Regression Algorithms used in Neural Networks [Future study topics] Regression Algorithms Regression algorithms are a category of machine learning methods used to predict a continuous numerical value. Linear regression is a simple, powerful, and interpretable algorithm for this type of problem. Quick Example: These are the scores of students vs. the hours they spent studying. Looking at this dataset of student scores and their corresponding study hours, can we determine what score someone might achieve after studying for a random number of hours? Example: From the graph, we can estimate that 4 hours of daily study would result in a score near 80. It is a simple example, but for more complex tasks the underlying concept will be similar. If you understand this graph, you will understand this blog. Sim...

                                          What problems can AI Neural Networks solve

                                          How does AI Neural Networks solve Problems? What problems can AI Neural Networks solve? Based on effectiveness and common usage, here's the ranking from best to least suitable for neural networks (Classification Problems, Regression Problems and Optimization Problems.) But first some Math, background and related topics as how the Neural Network Learn by training (Supervised Learning and Unsupervised Learning.)  Background Note - Mathematical Precision vs. Practical AI Solutions. Math can solve all these problems with very accurate results. While Math can theoretically solve classification, regression, and optimization problems with perfect accuracy, such calculations often require impractical amounts of time—hours, days, or even years for complex real-world scenarios. In practice, we rarely need absolute precision; instead, we need actionable results quickly enough to make timely decisions. Neural networks excel at this trade-off, providing "good enough" solutions in seco...

                                          Activation Functions in Neural Networks

                                            A Guide to Activation Functions in Neural Networks 🧠 Question: Without activation function can a neural network with many layers be non-linear? Answer: Provided at the end of this document. Activation functions are a crucial component of neural networks. Their primary purpose is to introduce non-linearity , which allows the network to learn the complex, winding patterns found in real-world data. Without them, a neural network, no matter how deep, would just be a simple linear model. In the diagram below the f is the activation function that receives input and send output to next layers. Commonly used activation functions. 1. Sigmoid Function 2. Tanh (Hyperbolic Tangent) 3. ReLU (Rectified Linear Unit - Like an Electronic Diode) 4. Leaky ReLU & PReLU 5. ELU (Exponential Linear Unit) 6. Softmax 7. GELU, Swish, and SiLU 1. Sigmoid Function                       The classic "S-curve," Sigmoid squashes any input value t...