0

I want to create a function that accepts an array of both arrays and literals (or maybe objects) and flattens it to a single dimensional array. For example a valid input would be [5, [2, 3], 7, [9, 0, 1]], and the output of that input should be [5, 2, 3, 7, 9, 0, 1].

This is the code I have so far. There is nothing wrong with it, I just want to make sure it's as efficient as possible (it also needs to be es5 compatible).

function flattenArray(list) {
  var result = [];
  for (var index = 0; index < list.length; index++) {
    result.push(list[index] instanceof Array ? list[index] : [list[index]]);
  }
  return [].concat.apply([], result);
}

console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));
nick zoum
  • 7,216
  • 7
  • 36
  • 80

2 Answers2

2

How about simply using Array.flat

function flattenArray(list) {
  return list.flat()
}

console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));

This seems to be second fastest ( based on the test link attached below ) and ES5 compatible

console.log([].concat.apply([],[5, [2, 3], 7, [9, 0, 1]]))

Performace test

Code Maniac
  • 37,143
  • 5
  • 39
  • 60
  • 3
    The question has `ecmascript-5`tag so I'd assume it's not looking for new ES features. – Clarity Aug 13 '19 at 10:56
  • 2
    @Clarity added one ES-5 compatible version too – Code Maniac Aug 13 '19 at 11:00
  • @CodeManiac Didnt realise `Array#concat` accepted mixed inputs. This is obviously faster. – nick zoum Aug 13 '19 at 11:01
  • this will not work for nested arrays, like `[0, [1, [2, [3, [4], [5], [6, [7], [8], [9]]]]]]` – Medet Tleukabiluly Aug 13 '19 at 11:15
  • 1
    @MedetTleukabiluly [`OP's comment`](https://stackoverflow.com/questions/57476260/most-efficient-way-to-flatten-array-of-arrays-and-literals-in-javascript/57476291#comment101424458_57476260) this is what op has mentioned in comment – Code Maniac Aug 13 '19 at 11:16
  • 1
    @MedetTleukabiluly but someone should not just directly copy paste code from here to there requirements, they should atleast try to understand a bit as well as read the question and comment properly, and also there's a good dup target is also on the top, – Code Maniac Aug 13 '19 at 11:24
  • @MedetTleukabiluly I don't think that the answers should also have to include another answer for questions that look like my question. Also i edited the title to make clarify the type. – nick zoum Aug 13 '19 at 11:32
  • @CodeManiac Did some [tests](http://jsben.ch/VLn9e), looks like `Array#push` is faster than `Array#concat` – nick zoum Aug 13 '19 at 11:35
  • @nickzoum when i run test it shows code block 2 (Array#concat ) is fastest, and also the test result will depend on the data set you're using for test, see the one i linked in question it uses a large data – Code Maniac Aug 13 '19 at 11:38
  • @CodeManiac I created a benchmark with larger data [here](http://jsben.ch/ZZ7I9). It says `Array#flat` is the slowest and nested `Array#push` is the fastest. – nick zoum Aug 13 '19 at 11:53
2

Cocerning your code: There is no sense in wrapping single elements into arrays, .concat will handle them correctly, in other words:

  [1].concat([2], 2)

just works, there is no need for wrapping 2 into [2]. That turns your code into a oneliner.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • All answers that I scrolled through also work for your usecase. What else do you need? – Jonas Wilms Aug 13 '19 at 11:14
  • The answers on that question could be possible answers for this question as well, yes. But the question is clearly not the same, and none of those answers is the most efficient way, as you can see in the benchmark [here](http://jsben.ch/ZZ7I9). – nick zoum Aug 13 '19 at 11:56
  • That benchmark runs on a very small sample set without any iterations. Whatever conclusion you try to draw from that is wrong. – Jonas Wilms Aug 13 '19 at 12:06
  • It's 500 iterations, also `http://jsben.ch` doesn't work if a case takes too long, it says that all the cases run in 0ms. Here's a [benchmark](http://jsben.ch/Mbpdk) with somewhat larger data (but without any iterations). – nick zoum Aug 13 '19 at 12:28