[JS interview question] Write a composite function

Require

Please write a function that receives a function array [f1, f2, f3,..., fn] and returns a new function fn, which is a composite function of the function array.

The composite function of [f(x), g(x), h(x)] is fn(x) = f(g(h(x))).

The composite function of an empty function list is the identity function f(x) = x.

You can assume that each function in the array accepts an integer parameter as input and returns an integer as output.

Example 1:

Input : functions = [x => x + 1, x => x * x, x => 2 * x], x = 4
Output : 65
Explanation :
Calculate from right to left...
Starting with x = 4.
2 * ( 4) = 8
(8) * (8) = 64
(64) + 1 = 65

Example 2:

Output : functions = [x => 10 * x, x => 10 * x, x => 10 * x], x = 1
Input : 1000
Explanation :
Counting from right to left...
10 * (1) = 10
10 * (10) = 100
10 * (100) = 1000

Example 3:

Input : functions = [], x = 42
Output : 42
Explanation :
The composite function of the empty function list is the identity function

solution

Overview

Function composition is a concept in functional programming where the output of one function is used as the input of another function. In other words, it is the process of chaining two or more functions together so that the result of one function becomes the input to the next function.

For example, here are two functions, f(x) and g(x):

const f = x => x + 2;
const g = x => x * 3;

The combination of these two functions is expressed as (f ∘ g)(x), that is, first apply the function g(x), and then use the result of g(x) as the input of f(x). In this case, (f ∘ g)(x) is:

const composedFunc = x => f(g(x)); // f(g(x)) = f(3x) = 3x + 2

So when we combine the functions f(x) and g(x), the resulting function (f ∘ g)(x) takes an input x, multiplies it 3(using g(x)), and then adds it 2(using f(x)).

Method 1: Use iterative function combinations

Overview

Function composition is a concept where we apply a sequence of functions to an input value in a specified order. In this problem, we need to combine the functions given in the array and create a new function that represents their combination. The order in which these functions are applied is from right to left. When the function array is empty, we should return the identity function and the input value it returns remains unchanged.

To solve this problem, we can iterate backwards starting from the last function in the array and apply each function to the input value in turn. We will apply the last function in the array starting from the input value x. We will then use the result as input to the previous function and continue this process until we reach the first function in the array. After applying all functions, we return the final result.

algorithm

  1. Inside composethe function, return another xfunction that accepts an input value.
  2. Checks whether the length of the function array is zero; if so, returns the identity function (i.e. returns x).
  3. xInitialize the variable with value input.
  4. Traverse the function array from the last index to the first index.
  5. For each function in the array, apply it to inputthe value and update the input value with the result.
  6. After iterating through all functions, return the final input value as the output of the combined function.

accomplish

Here's the implementation using a regular for loop:

var compose = function (functions) {
    
    
  return function (x) {
    
    
    if (functions.length === 0) return x;
    let input = x;

    for (let i = functions.length - 1; i >= 0; i--) {
    
    
      const currFunc = functions[i];

      input = currFunc(input);
    }

    return input;
  };
};

Implementation using for ... of loop:

var compose = function (functions) {
    
    
  return function (x) {
    
    
    if (functions.length === 0) return x;
    let input = x;

    for (const func of functions.reverse()) {
    
    
      input = func(input);
    }

    return input;
  };
};

Method 2: Use function combination of Array.reduceRight()

Overview

In the first method, we apply the function iteratively from right to left. However, we can utilize the Array.reduceRight() method to achieve the same result. The reduceRight() method applies a function to the accumulator and each element in the array (from right to left) to reduce them to a single value. In this case, our accumulator will be the input value x and the function will be the combination of functions in the array.

Using reduceRight() simplifies the code and provides a more functional programming style solution. The key is to understand how the Array.reduceRight() method works and how to apply it to this problem.

algorithm

  1. Inside composethe function, return another xfunction that accepts an input value.
  2. Use Array.reduceRight()the method to iterate the function from right to left.
  3. For each function in the array, apply it to the accumulator (initially x) and update the accumulator with the result.
  4. After iterating through all functions, return the final accumulator value as the output of the combined function.

accomplish

var compose = function(functions) {
    
    
    return x => functions.reduceRight((acc, f) => f(acc), x);
};

The key is to understand Array.reduceRight()how the method works.
Array.reduceRight() is a built-in JavaScript array method that applies a function to each element of the array, iterating from right to left. It takes two arguments: a reducerfunction and an optional initial value for the accumulator.
The reducer function itself takes four parameters: the accumulator, the current value, the current index, and the array being processed. The accumulator is a value that is built up on each iteration and ultimately returned at the end of the process. In our case, the accumulator represents the intermediate result when applying the functions in the combined function.

Here's a detailed explanation of how Array.reduceRight() works in the context of a compose function:

  1. The compose function takes an array containing functions and returns a new function that accepts the input value x.
  2. When a combined function is called with an input value x, it calls Array.reduceRight() on the function array.
    The reducer function iterates over each function in the array, starting with the rightmost element and moving to the left. The accumulator initially contains the input value x.
  3. On each iteration, the reducer function applies the current function to the accumulator and updates the accumulator with the result.
  4. Once all functions have been applied, the final value of the accumulator is returned.

To illustrate this process, consider a simple example:

const functions = [x => x * 2, x => x + 1];
const composedFn = compose(functions);
const result = composedFn(3); // 结果应该是 (3 + 1) * 2 = 8
  1. The compose function receives an array containing two functions: x => x * 2 and x => x + 1.
  2. When composedFn is called with an input value of 3, it calls Array.reduceRight() on the function array.
  3. The reducer function starts with the rightmost function x => x + 1 and applies it to the accumulator (initially 3). The accumulator becomes 3 + 1 = 4.
  4. The reducer function then moves to the next function x => x * 2 and applies it to the accumulator (which is now 4). The accumulator becomes 4 * 2 = 8.
  5. The final value of the accumulator, 8, is returned as the result of the combining function.

In summary, by using Array.reduceRight(), we can apply function composition in an easy and concise way.

Guess you like

Origin blog.csdn.net/owo_ovo/article/details/135274383