DEV Community

Amit Khonde
Amit Khonde

Posted on

JavaScript Interview: Write a custom reduce function

What is this series about?

Hello all! Welcome to the JavaScript interview questions series. In each post of this series, I will talk about the questions (specific to JavaScript) I faced in my recent interviews. This series will be helpful for you if you are preparing for JavaScript interviews or just started to deep dive into JavaScript and want to test your knowledge.

Post 3: Write your own custom reduce function

In today’s modern web development, a lot of us work on pretty modern tech stacks like React or Vue, or Angular. But in web development, a lot of projects today still function on legacy code and need active work. This is why, writing custom functions or polyfills for new JavaScript features is a popular interview question. Also, writing our own version of something that we use every day makes the concept easy and quick to grasp.

In one of my interviews, the interviewer asked me to write a custom function for Array.reduce(). Before diving further into this post, we must understand what Array.reduce() does. Here is a great post on MDN blog on what reduce does.

Now that we are all set, let us dive into writing our own reduce function. 💻 ⚔️

Question

Write a custom function like Array.reduce().

// Existing Array.reduce() function
const array = [10, 20, 30, 40];
const reducer = (accumulator, currentValue) => {
  return accumulator + currentValue;
}
const result = array.reduce(reducer);
console.log(result);
// expected output: 100


// Your code goes here
function customReduce(arr, reducer, initialValue = 0) {
  // Write Code
}

const customResult = customReduce(array, reducer, 0);
console.log(customResult);
Enter fullscreen mode Exit fullscreen mode

Before diving into the solution, I highly suggest that you try to solve this problem on your own. Here is a hint: Think about what reducer expects and what does it return?

Solution

As always, we are going to start with the least and do the obvious stuff first. So we can see that our custom function needs to return the final value.

function customReduce(arr, reducer, initialValue = 0) {
  var value;

  return value;
}
Enter fullscreen mode Exit fullscreen mode

Further, for each array element, our customReducer function needs to call the reducer function (passed in as a parameter). The reducer function expects following parameters:

  • The return value from previous execution.
  • Current array element
  • Current index
  • The array itself
function customReduce(arr, reducer, initialValue = 0) {
  var value;
  for (let i = 0; i < arr.length; i++) {
    value = reducer(value, arr[i], i, arr);
  }

  return value;
}
Enter fullscreen mode Exit fullscreen mode

Now you might be wondering what will happen to the intialValue? Well, we want intialValue to be the value passed to the first execution of the reducer function. We can do that by assigning that intialValue to value. So the final version of the customReduce function will look like this.

Edit:
As rightfully pointed by @kennethlum , if the initialValue is not passed, we should consider first element of the array as the initialValue.

function customReduce(arr, reducer, initialValue = null) {
  if (initialValue === null) {
    initialValue = arr[0];
  }

  var value = initialValue;
  for (let i = 0; i < arr.length; i++) {
    value = reducer(value, arr[i], i, arr);
  }

  return value
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Yay!! This looks like a working solution for now. I would love to know what approaches you can come up with for this problem. Do post your suggestions in the comments. And for more interesting questions like this, keep following this series. Until then, Happy Coding!!

Top comments (7)

Collapse
 
bugb profile image
bugb • Edited

A simple reduceRight using recursion implementation would be like this:

customReduce = (arr, reducer, initialValue = null) =>
  arr.length > 1 ?
  customReduce(arr.slice(1), reducer, reducer(arr[0], initialValue)) :
  reducer(arr[0], initialValue)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kennethlum profile image
Kenneth Lum

The current solution right now as of May 20, 2021, is that it uses function customReduce(arr, reducer, initialValue = 0) { which is to assume initialValue is 0, but it can't always be the case.

[1,3,5].reduce((a,b) => a * b)   // => 15
customReduce([1,3,5], (a,b) => a * b)   // => 0
Enter fullscreen mode Exit fullscreen mode

so essentially, one way is that when there is no initial value, we'd use the first value as the initial value instead.

Collapse
 
amitkhonde profile image
Amit Khonde

Thank you for pointing out Kenneth. Will edit that part definitely.

Collapse
 
tilkinsc profile image
Cody Tilkins

I would ding this for lack of input type checking. It's a must especially in a type-silent language.

Collapse
 
ajaymarathe profile image
Ajay Marathe

Helpful.

Collapse
 
junaidshaikhjs profile image
Junaid Shaikh

Nice article.

The for loop should start from 1 if no initial value is provided.

Collapse
 
__5fb02e7 profile image
Роман Барахвостов • Edited

customReduce([1,2,3,4,5], (a,b) => a + b) // 16, but expected 15.
You add 1 twice, first as an initial value, second as the first element of array