Skip to content

Instantly share code, notes, and snippets.

@tobiamos
Last active October 20, 2018 15:43
Show Gist options
  • Save tobiamos/df98132381f9d4bf8719a0e318be2e2b to your computer and use it in GitHub Desktop.
Save tobiamos/df98132381f9d4bf8719a0e318be2e2b to your computer and use it in GitHub Desktop.
Flatten a nested array in javascript
/* This function will flatten an array of arbitrarily nested
arrays of integers into a flat array of integers
it returns an array of flattened items
SETUP INSTRUCTIONS
make sure you have nodejs >= V6.0 installed
in your terminal make a new folder with mkdir flatten
navigate to the newly created folder with cd flatten
make a new file with touch index.js
install mocha and chai using npm install mocha chai
copy the contents from this file to index.js
run the test with ./node_modules/.bin/mocha index.js
*/
const { expect } = require('chai');
function flatten(input) {
if (!(input instanceof Array)) {
throw new Error('input must be an array');
}
const flat = input.reduce((acc, item) => {
if (Array.isArray(item)) {
acc.push(...flatten(item));
} else {
acc.push(item);
}
return acc;
}, []);
return flat;
}
describe('flatten array', () => {
it('should throw an error if item is not an array', () => {
try {
flatten('abcdef');
} catch (error) {
expect(error.message).to.eql('input must be an array');
}
});
it('should return an empty array if the array passed in is empty', () => {
const result = flatten([]);
expect(result).to.eql([]);
});
it('should return the input array if it alreay flat', () => {
const array = [1, 2, 3, 4];
const result = flatten(array);
expect(result).to.eql([1, 2, 3, 4]);
});
it('should flatten a nested array', () => {
const array = [1, 2, 3, [4, 5, 6, [7, [8, [[9, [[[10]]]]]]]]];
const result = flatten(array);
expect(result).to.eql([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
});
});
@stefanosala
Copy link

Hey Amos,
your code looks good! I've just one question: could you try to refactor so that const flat = gets the result of input.map?

Something like this:

  const flat = input.map((item) => {
    ...
  });

Thanks!
Stefano

@tobiamos
Copy link
Author

tobiamos commented Oct 16, 2018

Hi Stefano Thank you for your review, just seeing this, i don't think a refactor using map would work, i could use a reduce instead

function flatten(input) {
  if (!(input instanceof Array)) {
    throw new Error('input must be an array');
  }
  const flat = input.reduce((acc, item) => {
    if (Array.isArray(item)) {
      acc.push(...flatten(item));
    } else {
      acc.push(item);
    }
    return acc;
  }, []);
  return flat;
} 

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