Hone logo
Hone
Problems

Mastering Functional Programming: Recreating map, filter, and reduce in Python

Python's built-in map, filter, and reduce functions are powerful tools for functional programming, enabling concise and expressive data transformations. This challenge asks you to implement these functions from scratch, deepening your understanding of iteration, higher-order functions, and list manipulation.

Problem Description

Your task is to create three Python functions: my_map, my_filter, and my_reduce. These functions should mimic the behavior of Python's built-in map, filter, and functools.reduce respectively.

my_map(func, iterable): This function should take a function func and an iterable (e.g., a list, tuple) as input. It should apply func to each item in the iterable and return a new iterable containing the results. The order of elements in the output should correspond to the order in the input.

my_filter(func, iterable): This function should take a function func (which returns a boolean) and an iterable. It should iterate through the iterable and yield only those items for which func returns True. The order of elements in the output should be preserved from the input.

my_reduce(func, iterable, initializer=None): This function should take a binary function func (that accepts two arguments), an iterable, and an optional initializer. It should apply func cumulatively to the items of the iterable, from left to right, so as to reduce the iterable to a single value.

  • If initializer is provided, it should be used as the starting value.
  • If initializer is not provided, the first item of the iterable should be used as the starting value, and the reduction should begin from the second item.
  • If the iterable is empty and no initializer is provided, a TypeError should be raised.

Examples

Example 1: my_map

Input:
func = lambda x: x * 2
iterable = [1, 2, 3, 4]

Output:
[2, 4, 6, 8]

Explanation:
The lambda function doubles each element in the list.

Example 2: my_filter

Input:
func = lambda x: x % 2 == 0
iterable = [1, 2, 3, 4, 5, 6]

Output:
[2, 4, 6]

Explanation:
The lambda function checks for even numbers. Only elements that satisfy this condition are included in the output.

Example 3: my_reduce (with initializer)

Input:
func = lambda x, y: x + y
iterable = [1, 2, 3, 4]
initializer = 10

Output:
20

Explanation:
The reduction proceeds as follows:
10 + 1 = 11
11 + 2 = 13
13 + 3 = 16
16 + 4 = 20

Example 4: my_reduce (without initializer)

Input:
func = lambda x, y: x * y
iterable = [2, 3, 4]

Output:
24

Explanation:
The reduction proceeds as follows:
2 * 3 = 6
6 * 4 = 24

Example 5: my_reduce (edge case: empty iterable with initializer)

Input:
func = lambda x, y: x + y
iterable = []
initializer = 0

Output:
0

Explanation:
The initializer is returned directly as the iterable is empty.

Example 6: my_reduce (edge case: empty iterable without initializer)

Input:
func = lambda x, y: x + y
iterable = []

Output:
TypeError: reduce() of empty sequence with no initial value

Explanation:
An empty iterable with no initializer should raise a TypeError.

Constraints

  • Your implementations of my_map, my_filter, and my_reduce must not use Python's built-in map, filter, or functools.reduce functions.
  • Your my_map and my_filter functions should return iterators (or generator expressions), not lists, to align with the lazy evaluation behavior of the built-ins.
  • For my_reduce, ensure correct handling of empty iterables and the optional initializer.
  • The input iterable can be any Python iterable (list, tuple, etc.).
  • The function func passed to my_map and my_filter should be a callable.
  • The function func passed to my_reduce should be a callable that accepts exactly two arguments.

Notes

  • Consider how to handle different types of iterables.
  • Think about the use of yield for my_map and my_filter to create generators.
  • For my_reduce, pay close attention to the initialization logic and how to gracefully handle the absence of an initializer.
  • Test your functions with various inputs, including empty iterables and iterables with different data types.
Loading editor...
python