Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I want to define a function .flatten that flattens several elements into one single array. I know that the following is not possible, but essentially I would like to do this:

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]

I get the following error:

TypeError: arguments.reduce is not a function

I understand that the above error is because arguments is only array-like, so it does not have the full capabilities of a true array. So there is the following, but I'm wondering if there is something even cleaner:

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

Any good way to rewrite .flatten using .reduce()?

NOTE: I know there are many other ways that you can flatten arrays in javascript, but what I was wondering about here is how to do so with specifically arguments.

like image 281
Aljosha Novakovic Avatar asked Dec 14 '22 04:12

Aljosha Novakovic


2 Answers

Convert the arguments object to an array first:

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

Or, use array methods on the arguments object directly:

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

In ES6, you can use Array.from() to convert any iterable or array-like object to an actual array:

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

Update in 2021 using modern language features:

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

And, you can pass a depth to .flat(n) (default is 1) if you want to flatten to a deeper level than just one level down.

Though, since we have these more modern features now built into the language, you probably can use them more directly rather than passing them to a function to work on them, but we'd have to see some particular use cases to make suggestions for inline ways to solve your problem rather than using this function.


FYI, there are lots of ways to flatten an array:

Merge/flatten an array of arrays

How to flatten nested array in javascript?

Flattening multidimensional Arrays in JavaScript

Array.prototype.flat() method

like image 69
jfriend00 Avatar answered Mar 22 '23 22:03

jfriend00


Use Array.prototype.concat.apply([], arguments)

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

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

If that looks ugly, and you don't mind creating an unused empty array, you can use:

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

In ES6 though, you can get the best of both worlds:

[].concat(...arguments)
like image 38
4castle Avatar answered Mar 22 '23 23:03

4castle