Skip to content

Instantly share code, notes, and snippets.

@thetutlage
Last active January 31, 2020 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save thetutlage/6d6bbbb68bbb5fa1facc318fd25e27e7 to your computer and use it in GitHub Desktop.
Save thetutlage/6d6bbbb68bbb5fa1facc318fd25e27e7 to your computer and use it in GitHub Desktop.
Flatten an array in Javascript without recursion
'use strict'
var Benchmark = require('benchmark')
var suite = new Benchmark.Suite;
var list = [1, 2, 3, [[4]], [[[5]]], [6], [[7]]]
function flattenRecursive (list) {
var flatList = []
list.forEach(function (item) {
if (item instanceof Array === true) {
flatList = flatList.concat(flattenRecursive(item))
} else {
flatList.push(item)
}
})
return flatList
}
function flatten (list) {
var clonedList = list.slice(0)
var flatList = []
while (clonedList.length) {
var item = clonedList.shift()
if (item instanceof Array === true) {
clonedList = item.concat(clonedList)
} else {
flatList.push(item)
}
}
return flatList
}
suite.add('flattenRecursive', function() {
flattenRecursive(list)
})
.add('flatten', function() {
flatten(list)
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run()
@jacoborus
Copy link

Your tests are running over an empty array. Try this in every test instead passing list var:

function getList () {
  return [1, 2, 3, [[4]], [[[5]]], [6], [[7]]]
}
.add('flatten', function() {
  flatten(getList())
})

@Hypercubed
Copy link

@thetutlage I think the majority of the performance difference between the flattenRecursive and flatten is that .forEach is very slow. Try this:

function flattenRecursive2 (arr) {
  var flatList = []
  var i = -1;
  var len = arr.length - 1;
  while (i++ < len) {
    if (Array.isArray(arr[i])) {
      flatList = flatList.concat(flattenRecursive2(arr[i]))
    } else {
      flatList.push(arr[i])
    }
  }
  return flatList;
}

or how about how about:

function flattenRecursive3(array) {
  return (function traverse(arr, flatList) {
    var i = -1;
    var len = arr.length - 1;
    while (i++ < len) {
      if (Array.isArray(arr[i])) {
        traverse(arr[i], flatList);
      } else {
        flatList.push(arr[i])
      }
    }
    return flatList;
  })(array, []);
}

@gauravmuk
Copy link

gauravmuk commented Feb 22, 2017

@thetutlage the solution with recursion is much faster when written in the right way :) https://jsperf.com/flatten-array-r1

@rofrol
Copy link

rofrol commented Jan 31, 2020

@gauravmuk your link is 404

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment