最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I write my own `reduce` function? - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question edited Oct 31, 2016 at 21:34 jacefarm 7,4316 gold badges37 silver badges46 bronze badges asked Oct 31, 2016 at 20:34 SergeyBSergeyB 3352 gold badges3 silver badges11 bronze badges 2
  • 3 You don't need to use arguments - declare them explicitly as function(reducer, initialValue) – zerkms Commented Oct 31, 2016 at 20:39
  • 3 Have you taken a look at the Polyfill on MDN? That should give you some hints – UnholySheep Commented Oct 31, 2016 at 20:40
Add a comment  | 

11 Answers 11

Reset to default 7

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

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'));

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.

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.

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));

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.......

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

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
const arr = [1,2,2,4];

 Array.prototype.handReducer = function(cb,value) {
    this.forEach(ele => value = cb(ele,value))
    console.log(value)//9
    return value;
}
const cb = (arr,value) => arr + value;
const new_arr = arr.handReducer(cb,0)
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;
}
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))  
发布评论

评论列表(0)

  1. 暂无评论