我如何写我自己的“减少”函数

How do I write my own `reduce` function?

本文关键字:减少 函数 自己的 何写我      更新时间:2023-09-26

我想自己写reduce。但在过去的4个小时里,我做不到。

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

是的,我知道这看起来像很多话题,但是我找不到答案。我遗漏了什么,或者做错了什么?

subject中的数组不是作为参数传递的,而是上下文(this)。

您还需要区分是否存在起始值:

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

使用ES6默认参数:

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

基于您的代码

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

我不确定我的答案是否完全回答了这个问题,但我希望这可能对某人有所帮助。

不使用原型和循环的例子:

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

和循环的例子:

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
}

正如你所看到的,在第一个例子中,我们没有分配变量,我们只有一些常量,但在循环的例子中,我们分配了acc变量

下面的代码将传递的数组简化为单个值。需要传递一个函数,告诉数组需要做什么,如果需要,传递一个初始值。

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是一个自定义的reduce函数,它接受一个回调函数(fn)和一个可选的初始值。它就像减速器一样工作。
  • 回调函数 function(total,x){return total + x}作为参数传递给myFunction,然后减少为单个值。这里我们可以执行任何类似于reduce的操作,而不是add。

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

实际缩减函数:

const list = [1,2,3,4,5];
const sum = list => list.reduce((total, val)=> total+val, 0)
console.log(sum(list));

如果我们仔细看,我们需要三样东西:一个要迭代的列表,初始值和一个reduce函数

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

思路是一样的。我们可以遵循同样的思路,编写不同的reduce函数来计数单词.......

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