您将如何在参数而不是特定数组或对象上使用 .reduce()?

How would you use .reduce() on arguments instead of a specific array or object?

我想定义一个函数 .flatten,将多个元素展平到一个数组中。我知道以下是不可能的,但基本上我想这样做:

var flatten = function() {
   var flattened = arguments.reduce(function(acc, elem) { return acc.concat(elem) }, []);
   return flattened;
}; 

var arr = [[1,2,3], 4, 5, [6, 7]];
console.log(flatten(arr)) // => [1,2,3,4,5,6,7]

我收到以下错误:

TypeError: arguments.reduce is not a function

我明白上面的错误是因为参数只是类数组,所以它不具备真正数组的全部功能。所以有以下内容,但我想知道是否有更干净的东西:

var flatten = function() {
  var flattened = [].reduce.call(arguments, function(acc, elem) { return acc.concat(elem) });
  return flattened;
};

有什么好的方法可以使用 .reduce() 重写 .flatten 吗?

注意:我知道还有许多其他方法可以在 javascript 中展平数组,但我想知道的是如何使用特定的 arguments.

首先将arguments对象转换为数组:

var flatten = function() {
   var args = Array.prototype.slice.call(arguments);
   var flattened = args.reduce(function(acc, elem) { return acc.concat(elem) }, []);
   return flattened;
};

或者,直接在 arguments 对象上使用数组方法:

var flatten = function() {
   var flattened = Array.prototype.reduce.call(arguments, function(acc, elem) { return acc.concat(elem) }, []);
   return flattened;
};

在 ES6 中,您可以使用 Array.from() 将任何可迭代或类数组对象转换为实际数组:

var flatten = function() {
   var args = Array.from(arguments);
   var flattened = args.reduce(function(acc, elem) { return acc.concat(elem) }, []);
   return flattened;
};

2021 年使用现代语言功能更新:

function flatten(...args) {
    return args.flat();
}

而且,如果你想展平到更深的层次,而不是仅仅向下一层,你可以将深度传递给 .flat(n)(默认为 1)。

虽然,由于我们现在将这些更现代的功能内置到语言中,您可能可以更直接地使用它们,而不是将它们传递给函数来处理它们,但我们必须看到一些特定的用例就内联方法提出建议来解决您的问题,而不是使用此功能。


仅供参考,有很多方法可以展平数组:

Merge/flatten an array of arrays

How to flatten nested array in javascript?

Flattening multidimensional Arrays in JavaScript

Array.prototype.flat() method

使用Array.prototype.concat.apply([], arguments)

function flatten() {
    return Array.prototype.concat.apply([], arguments);  
}

console.log(flatten([1, 2], 3, 4, [5, 6]));

如果这看起来很难看,而且您不介意创建一个未使用的空数组,您可以使用:

[].concat.apply([], arguments)

不过在 ES6 中,您可以两全其美:

[].concat(...arguments)

您还可以通过这种方式测试元素是否为子数组:

function flatten(arr){
   var res = [];
   arr.forEach(x => Array.isArray(x) ? x.forEach(y => res.push(y)) : res.push(x));
  return res;
}

console.log(flatten([[1,2,3], 4, 5, [6, 7]])); // [ 1, 2, 3, 4, 5, 6, 7 ]

像这样:

顺便说一句:我认为使用 pushconcat 更好,因为这不会创建新数组

function flatten() 
{
  return flatten0([], Array.from(arguments));

  function flatten0(res, arrToFlatten)
  { 
    for (let el of arrToFlatten)
      Array.isArray(el) ? flatten0(res, el) : res.push(el);
    return res;
  }
}; 

let arr = [1, 2, [3, 4], [[5, [6], [[7]]]]];
console.log(flatten(arr)) // [ 1, 2, 3, 4, 5, 6, 7 ]

希望我的回答对您有所帮助,我知道这个 post 是 2016 年的。

function flatten(...args){

    const values= args.reduce(function sumNumss(total,element){  
        return `${total} ${element}`
    });
    
    return values
}

flatten('sdfe',[1,23,1,23],'sedfe')

对参数使用其余的 (...args) 语法应该可以解决问题。