Reduce: The Swiss Army Knife of Basic Functional Programming
Published: 2023-04-21 18:09:50

---
title: Reduce: The Swiss Army Knife of Basic Functional Programming
published: true
description: 
tags: 
# cover_image: https://labs.openai.com/e/Eisb1QJRcNHyhgnn2MFX3U3A/unY8WSqBGZypHNEszIx5AJpk
# Use a ratio of 100:42 for best results.
# published_at: 2023-04-15 23:05 +0000
---
Functional programming is a paradigm that emphasizes the use of pure functions, immutable data, and higher-order abstractions. One of the most common and powerful higher-order abstractions in functional programming is the reduce function.

The reduce function takes an iterable (array, list, or other collection) and a function that combines two values, and applies that function to all the elements of the iterable returning a single value (which could be a primitive or an object). The canonical example is summing up an array of numbers.

```python
# Python code
numbers = [1, 2, 3, 4, 5]
sum = reduce(lambda x, y: x + y, numbers)
assert (sum == 15) # True
```
```typescript
// Typescript code
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((x, y) => x + y);
assert (sum === 15); // true
```
The power of the reduce function is its versatility. It can be used to implement many other iterable operations such as map, filter, find, etc.

For example, a filter function is just an implementation of reduce. Let’s see how we can use the reduce function to create our own filter function. A filter function takes an iterable and a predicate (a function that returns true or false), and returns a new object with only the elements that satisfy the predicate. To use the reduce function as a filter function, we need to define a filter function. 

```python
# Python code
def filter_by(acc, cur):
  # Check if the current element satisfies the condition using the boolean function
  if condition(cur):
    # If True, append the current element to the accumulator array
    acc.append(cur)
  
  # Return the accumulator list
  return acc
```
```typescript
// Typescript code
function filterBy(acc: any[], cur: any): any[] {
  // Check if the current element satisfies the condition using the boolean function
  if (condition(cur)) {
    // If true, push the current element to the accumulator array
    acc.push(cur);
  }

   // Return the accumulator array
   return acc;
}
```
Now we can use this function with the reduce function to filter out the even numbers from an array of numbers.

```python
# Python code
numbers = [1, 2, 3, 4, 5]

# Define a boolean function that checks if a number is odd
def condition(x):
  return x % 2 == 1

# Use reduce and filter_by to filter out the even numbers from numbers
odd_numbers = reduce(filter_by, numbers, [])

print(odd_numbers) # [1, 3, 5]
```
```typescript
// Typescript code
const numbers = [1, 2, 3, 4, 5];

// Define a boolean function that checks if a number is odd
function condition(x: number): boolean {
  return x % 2 == 1;
}

// Use reduce and filterBy to filter out the even numbers from numbers
const oddNumbers: number[] = numbers.reduce(filterBy, []);

console.log(oddNumbers); // [1,3,5]
```

Now, let's use reduce to return a Record object. If you have an array of strings that represent colors, you can use a reduce function to count how many times each color appears in the array and return an object with the color names as keys and the counts as values.

```python
# Import reduce from functools module
from functools import reduce

# Define a list of colors
colors = ["red", "blue", "green", "red", "yellow", "blue", "green", "red"]

def get_color_counts(colors):
  # Use reduce on the list
  return reduce(lambda counts, color: 
    # For each color, check if it already exists as a key in the counts dictionary
    counts.update({color: counts.get(color, 0) + 1}) or counts
    # If yes, increment its value by one
    # If no, initialize its value to one
    # Use update and get methods on the dictionary and return the updated counts dictionary
  , colors, {}) # Start with an empty dictionary for the counts

print(get_color_counts(colors)) # {'red': 3, 'blue': 2, 'green': 2, 'yellow': 1}
```
```typescript
// Typescript code

const colors: string[] = ["red", "blue", "green", "red", "yellow", "blue", "green", "red"];

function getColorCounts(colors: string[]): Record<string, number> {
  // Use the reduce method on the array
  return colors.reduce((counts: Record<string, number>, color: string) => {
    // For each color, check if it already exists as a key in the counts object
    if (counts[color]) {
      // If yes, increment its value by one
      counts[color] += 1;
    } else {
      // If no, initialize its value to one
      counts[color] = 1;
    }
    // Return the updated counts object
    return counts;
  }, {}); // Start with an empty object for the counts
}

console.log(getColorCounts(colors)); // {red: 3, blue: 2, green: 2, yellow: 1}
```
Those are just a few examples of the powerful functional nature of a reduce function that allows for concise and expressive transformations of iterable data structures. It can be used to implement many other higher-order functions such as map, filter, and find. The reduce function can help simplify complex computations and make code more elegant and efficient.