Higher-Order Functions
Problem Statement
Use map, filter, and reduce to process data.
Background
Python provides functional programming tools:
- map(func, iterable) - apply function to each element
- filter(func, iterable) - keep elements where func returns True
- reduce(func, iterable) - combine elements pairwise (from functools)
Your Task
Write a function process_numbers(numbers) that applies various higher-order functions.
Output Format
Return a dictionary with:
- "doubled": All numbers doubled (use map)
- "evens": Only even numbers (use filter)
- "product": Product of all numbers (use reduce)
- "sum_of_squares": Sum of squared numbers (use map+reduce)
Example:
[1, 2, 3, 4, 5]
{'doubled': [2, 4, 6, 8, 10], 'evens': [2, 4], 'product': 120, 'sum_of_squares': 55}map(lambda x: x2), filter(lambda x: x%2==0), reduce(lambda a,b: ab)
Constraints:
- Use map, filter, and reduce from functools
- Numbers list will have at least 1 element
Background Knowledge
Higher-order functions in Python enable functional programming paradigms by treating functions as first-class citizens—capable of being passed as arguments, returned from other functions, or assigned to variables. map, filter, and reduce are core examples: map(func, iterable) applies func to each element of iterable, producing a new iterable without mutating the original; filter(func, iterable) yields elements where func evaluates to True; and reduce(func, iterable) from functools iteratively applies func to accumulate a single value (e.g., sum or product) by pairwise combination.
These functions promote concise, declarative code over imperative loops, enhancing readability and parallelism potential. For instance, map transforms data uniformly, filter selects subsets based on predicates, and reduce aggregates via binary operations. Composing them (e.g., map followed by reduce) handles complex transformations efficiently, as seen in data processing pipelines. Empirical studies note that while functional constructs like these can introduce bugs if misused, they reduce side effects compared to loops.
Algorithm/Approach
The pattern leverages composition of higher-order functions to transform and aggregate list data into dictionary keys:
- Use map for element-wise transformations (e.g., doubling or squaring).
- Apply filter for conditional selection (e.g., even numbers).
- Employ reduce for folding (e.g., product via multiplication, sum via addition). Return a dictionary mapping string keys to these computed results, ensuring immutability and functional purity.
This mirrors MapReduce paradigms for scalable processing: map scatters transformations, reduce gathers aggregations.
Step-by-Step Strategy
- Import required module: Start with from functools import reduce to access reduce.
- Doubled values: Apply map with a lambda or function that multiplies each number by 2; convert result to list.
- Even numbers: Use filter with a predicate checking num % 2 == 0; convert to list.
- Product: Invoke reduce with a lambda multiplying pairwise (lambda x, y: x * y); handle empty lists if needed.
- Sum of squares: Chain map to square each number (lambda x: x**2), then reduce to sum (lambda x, y: x + y).
- Package results: Construct and return {"doubled":..., "evens":..., "product":..., "sum_of_squares":...}.
Test with sample [1, 2, 3, 4, 5] to verify outputs match expected dictionary.
Common Pitfalls
- Forgetting import: reduce requires functools; NameError otherwise.
- List conversion: map and filter return iterators—use list() for dictionary storage, as iterators are exhausted once.
- Empty iterable: reduce raises TypeError on empty lists without initializer (e.g., reduce(lambda x,y: x*y, [])); provide default like 0 for sum or 1 for product.
- Mutability: Avoid modifying input numbers; higher-order functions are non-destructive.
- Lambda syntax: Ensure binary lambdas for reduce (two args); test edge cases like negatives or zeros (product becomes zero).
- Type consistency: Ensure outputs match sample (lists for doubled/evens, ints for aggregations).
Time & Space Complexity
- Time: O(n) per operation (map/filter/reduce each scan list once), total O(n) for all keys, where n=len(numbers).
- Space: O(n) for lists from map/filter (doubled/evens); O(1) for reduce scalars. Overall O(n) due to output dictionary; iterators minimize temp space if not listed early.
| Operation | Time | Space |
|---|---|---|
| doubled | O(n) | O(n) |
| evens | O(n) | O(n) |
| product | O(n) | O(1) |
| sum_squares | O(n) | O(1) |