Skip to content

Instantly share code, notes, and snippets.

@Zyst
Last active May 4, 2019 20:09
Show Gist options
  • Save Zyst/63d3bfaecc66a792e8484a4a41fc9018 to your computer and use it in GitHub Desktop.
Save Zyst/63d3bfaecc66a792e8484a4a41fc9018 to your computer and use it in GitHub Desktop.
/**
* For the comments marked as "NOTE" I normally wouldn't include as comments
* in an actual program, but I felt they were aspects that needed I'd talk
* about if I were explaining it in a whiteboard-type interview.
*
* I also added "array-flatten-non-verbose.js" which is what I'd show if I had to
* "Ship to production", and my tests were grabbing the flattenArray, and
* recursiveFlatten function somewhere like jest to run more formal tests
*
* https://gist.github.com/Zyst/63d3bfaecc66a792e8484a4a41fc9018#file-array-flatten-non-verbose-js
*/
// Takes in an array, and optionally an array of existing results, for
// non-array items we add them to results, for array items we call ourselves
// then we return our flat results array
const recursiveFlatten = (array, results = []) => {
array.forEach(a => {
// NOTE: If we have an array, we call recursive flatten on it, passing
// in our results array, since this is all sequential, and arrays
// are shared in memory in JS this works as expected when we return
// results at the end of our function
if (Array.isArray(a)) {
recursiveFlatten(a, results);
} else {
// NOTE: Here, if as the spec. mentioned we wanted all items to be
// integers is where we would validate it. I imagined
// that wasn't part of the spec, but if it were I'd
// ask clarifying questions about it before writing
// the solution
results.push(a);
}
});
return results;
};
// Will flatten an array of arbitrarily nested items into a flat
// array of items. e.g. [[1,2,[3]],4] -> [1,2,3,4].
const flattenArray = arrayToFlatten => {
// NOTE: If the item we got passed isn't an array, we should just return an empty
// array to avoid bad usage of this function throwing in applications, this
// too would be a clarifying question
if (!Array.isArray(arrayToFlatten)) {
return [];
}
return recursiveFlatten(arrayToFlatten);
};
// This is a small utility function for testing array lengths, which is the main
// way I decided to test my flattenArray function
const expectLength = (array, expectedLength) => {
if (!Array.isArray(array)) {
throw new Error("expectLength expects an array");
}
if (array.length !== expectedLength) {
throw new Error(
`Array length mismatch, got ${array.length}, expected ${expectedLength}.`
);
}
};
// In case of non-array inputs, we should get an empty array back
expectLength(flattenArray({}), 0);
expectLength(flattenArray(""), 0);
// Properly flattens arrays
expectLength(flattenArray([[1, 2, [3]], 4]), 4);
expectLength(flattenArray([[1, 2, [3]], 4]), 4);
expectLength(flattenArray([0, [1, 2, 3, [4, [5, [6]]]]]), 7);
// Works with non-numbers too
expectLength(flattenArray([{}, null, {}, 4]), 4);
// Works with empty arrays
expectLength(flattenArray([]), 0);
// Expect [ 0, 1, 2, 3, 4, 5, 6, null, undefined, {} ]
console.log(
flattenArray([0, [1, 2, 3, [4, [5, [6, null, [undefined, {}, []]]]]]])
);
// Takes in an array, and optionally an array of existing results, for
// non-array items we add them to results, for array items we call ourselves
// then we return our flat results array
export const recursiveFlatten = (array, results = []) => {
array.forEach(a => {
if (Array.isArray(a)) {
recursiveFlatten(a, results);
} else {
results.push(a);
}
});
return results;
};
// Will flatten an array of arbitrarily nested items into a flat
// array of items. e.g. [[1,2,[3]],4] -> [1,2,3,4].
export const flattenArray = arrayToFlatten => {
if (!Array.isArray(arrayToFlatten)) {
return [];
}
return recursiveFlatten(arrayToFlatten);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment