'How do I write my own `reduce` function?
I want write reduce
by myself. But over the last 4 hours, I couldn't.
var a = [10, 21, 13, 56];
function add(a, b) { return a + b }
function foo(a, b) { return a.concat(b) }
Array.prototype.reduce2 = function () {
// I do not understand how to handle the function of the inlet
// I know that I should use arguments, but I don't know how many arguments there will be
var result = 0;
for(var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
};
console.log(a.reduce(add), a.reduce2(add)) // 100 100
console.log(a.reduce(add, 10), a.reduce2(add, 10)) // 110 110
Yes, I know that this seems like a lot of topics, but I couldn't find answer. What am I missing, or doing wrong here?
Solution 1:[1]
The array in subject is not passed as argument, but is the context (this
).
You also need to distinguish between the presence or absence of the start value:
var a = [10, 21, 13, 56];
function add(a, b) { return a + b }
function foo(a, b) { return a.concat(b) }
Array.prototype.reduce2 = function (f, result) {
var i = 0;
if (arguments.length < 2) {
i = 1;
result = this[0];
}
for(; i < this.length; i++) {
result = f(result, this[i], i, this);
}
return result;
};
console.log(a.reduce(add), a.reduce2(add)) // 100 100
console.log(a.reduce(add, 10), a.reduce2(add, 10)) // 110 110
// extra test with foo:
console.log(a.reduce(foo, 'X'), a.reduce2(foo, 'X')) // X10211356 X10211356
Solution 2:[2]
Based on your code
var a = [10, 21, 13, 56];
function add(a, b) { return a + b }
function foo(a, b) { return a.concat(b) }
Array.prototype.reduce2 = function(fn, start){
var result = start !== undefined ? start : this[0];
for (var i = 0; i < this.length; i++) {
result = fn(result, this[i]);
}
return result;
};
console.log(a.reduce(add), a.reduce2(add)) // 100 100
console.log(a.reduce(add, 10), a.reduce2(add, 10)) // 110 110
console.log(a.reduce(foo, ''), a.reduce2(foo, ''));
console.log(a.reduce(foo, 'X'), a.reduce2(foo, 'X'));
Solution 3:[3]
I'm not sure that my answer is exactly answering the question, but I hope this may help someone.
Example without using prototype and loops:
const origArr = [2,2]
const origFunc = (p,c) => p+c
const initial = 1
const reduce = (func, array, initial) => {
const rec = (arr, acc) => {
// arr: [2, 2], [2], []
// acc: 1, 3, 5
if (!arr.length) return acc
const curr = arr[0]
const nextArr = arr.slice(1)
const nextAcc = func(acc, curr)
return rec(nextArr, nextAcc)
}
if (initial) {
return rec(array, initial)
}
return rec(array.slice(1), array[0])
}
console.log(origArr.reduce(origFunc, initial)) // 5
console.log(reduce(origFunc, origArr, initial)) // 5
And example with loop:
const reduceLoop = (func, array, initial) => {
let acc = initial !== undefined ? initial : array[0]
let arr = initial !== undefined ? [initial, ...array] : array
for(let i=1;i<arr.length;i++) {
acc = func(acc, arr[i])
}
return acc
}
As you you can see, in first example we do not assigning variables, we just have some constants, but in the example with loop we assigning tha acc
variable.
Solution 4:[4]
Below code reduces the passed array to single value. Need to pass a function on what has to be done on the array and initial value if needed.
Array.prototype.myFunction = function(fn,initial) {
let arayEl = this;
console.log(arayEl);
let total = initial || 0;
for(let i=0;i<arayEl.length;i++) {
total = fn(total,arayEl[i]);
}
return total;
}
console.log([1,2,3].myFunction(function(total,x){return total +x},10));
console.log([1,2,3].reduce(function(total,x){return total +x},10));
console.log([1,2,3].myFunction(function(total,x){return total * x},10));
console.log([1,2,3].reduce(function(total,x){return total * x},10));
- myFunction is custom reduce function which accepts a callback funtion(fn) and a initial value which is optional. It will work just like reducer.
- callBack function function(total,x){return total + x} is passed as param to myFunction which is then reduced to single value. Here instead of add, we can perform any operation same like reduce.
Solution 5:[5]
const reduceV1 = (list, cb, intial) => {
let memo = intial;
for (let i = 0; i < list.length; i++) {
if (i === 0 && memo === undefined) {
memo = list[0];
} else {
memo = cb(list[i], memo);
}
}
return memo;
};
function sumV1(n, sum) {
return n + sum;
}
console.log(reduceV1([1, 2], sumV1));
console.log(reduceV1([1, 2,3], sumV1,0));
Solution 6:[6]
Actual reduce fuction:
const list = [1,2,3,4,5];
const sum = list => list.reduce((total, val)=> total+val, 0)
console.log(sum(list));
If we look closely then we need three things: a list to iterate over , initial value and a reduce function
const reduceHelper = (list, initialValue, reducer) => {
// If the list is empty we will just return initial value
if(list.length === 0) {
return initialValue;
} else {
const [first, ...rest] = list;
const updatedAcc = reducer(initialValue, first);
return reduceHelper(rest, updatedAcc, reducer);
}
}
// test it
const list = [1,2,3,4,5];
console.log( myReduce(list, 0, (total, val) => total + val))
The idea is the same. We can follow the same idea and write different reduce function for counting words.......
Solution 7:[7]
Array.prototype.myReduce = function(callback, initialValue) {
var a = initialValue;
for(let i=0; i<this.length;i++){
callback(a=a+this[i]);
}
return a;
}
var arr = [1,2,3,4,5];
var result = arr.myReduce((next,prev) =>next+prev,10);
console.log(result); //25
Solution 8:[8]
With ES6 Default Parameters:
const nums = [1, 5, 5, 9];
Array.prototype.customReduce = function (callback, initial=0) {
let result = initial;
for (let i = 0; i < this.length; i++) {
result = callback(result, this[i]);
}
return result;
};
const sum = nums.customReduce((acc, value) => acc + value, 0);
console.log(sum); // 20
Solution 9:[9]
Array.prototype.customReduce = function (callback, initial) {
const arr = this
for (let i = 0; i < arr.length; i++) {
if (initial === undefined && i === 0) {
initial = arr[0]
continue
}
initial = callback(initial, arr[i], i)
}
return initial
}
Solution 10:[10]
var a = [10, 21, 13, 56];
function add(a, b) { return a + b }
Array.prototype.reduce2 = function(fn, start){
var result = start !== undefined ? start : this[0];
for (var i = 1; i < this.length; i++) {
result = fn(result, this[i]);
}
return result;
};
console.log(a.reduce(add), a.reduce2(add))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | |
Solution 5 | ASHISH R |
Solution 6 | ASHISH R |
Solution 7 | Utkarsh Joshi |
Solution 8 | Mr.spShuvo |
Solution 9 | harutyunian |
Solution 10 | Bhaskar Mishra |