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

问题描述 投票:0回答:5

我想定义一个函数 .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

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

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

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

注意:我知道还有很多其他方法可以在 javascript 中展平数组,但我在这里想知道的是如何使用特定的arguments来实现这一点。

javascript arguments reduce flatten
5个回答
11
投票

首先将

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

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


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

合并/展平数组的数组

如何在javascript中展平嵌套数组?

在 JavaScript 中展平多维数组

Array.prototype.flat()方法


1
投票

使用

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)

1
投票

我希望我的回答有帮助,我知道这篇文章是 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) 语法作为参数应该可以解决问题。


0
投票

您还可以这样测试元素是否是子数组:

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 ]

0
投票

类似这样的:

顺便说一句:我认为使用

push
concat
更好,因为这不会创建新数组

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 ]
© www.soinside.com 2019 - 2024. All rights reserved.