0% found this document useful (0 votes)
2 views

Flatten _ JavaScript Interview Questions with Solutions

The document discusses various methods to implement a 'flatten' function in JavaScript that recursively flattens nested arrays into a single-level array. It includes examples, clarification questions for interviews, and multiple solution approaches such as iterative, recursive, and in-place methods. Additionally, it mentions potential pitfalls like stack overflow with deep nesting and introduces bonus solutions that utilize JSON and other techniques.

Uploaded by

Parth Tiwari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Flatten _ JavaScript Interview Questions with Solutions

The document discusses various methods to implement a 'flatten' function in JavaScript that recursively flattens nested arrays into a single-level array. It includes examples, clarification questions for interviews, and multiple solution approaches such as iterative, recursive, and in-place methods. Additionally, it mentions potential pitfalls like stack overflow with deep nesting and introduces bonus solutions that utilize JSON and other techniques.

Uploaded by

Parth Tiwari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

Interviews

11 // Flattens recursively.
12 flatten([1, [2, [3, [4, [5]]]]]); // [1, 2, 3, 4,

Flatten Companies
Zhenghao He
Engineering Manager, Robinhood Amazon Apple Lyft Salesforce Google
Medium 20 mins 7.05k done
Implement a function flatten that returns a newly- Coding and submission is not supported on
mobile devices. Use a wider screen to practice
created array with all sub-array elements concatenated solving this question within the editor.
recursively into a single level.

Examples Hide solution

This is a common JavaScript interview question. It tests


1 // Single-level arrays are unaffected.
one's knowledge about checking for the array type,
looping through an array, various native methods such as
2 flatten([1, 2, 3]); // [1, 2, 3]
3
4 // Inner arrays are flattened into a single level. Array.prototype.concat , and recursion.
5 flatten([1, [2, 3]]); // [1, 2, 3]

Clarification Questions
6 flatten([
7 [1, 2],
8 [3, 4],
9 ]); // [1, 2, 3, 4] 1. What type of data does the array contain? Some
10 approach only applies to certain data types.

2. How many levels of nesting can this array have? If Then, we don't want to mutate the original input array,
there are thousands-of-levels of nesting, recursion which is a good practice in general, so we will make a
might not be a good idea given its big upfront copy of the input array and return a new array with all
memory footprint. the items extracted from the input array.
3. Should we return a new array or we mutate the Here is the solution. We loop through the array with a
existing array? while loop and we take out an item from the array one at
4. Can we assume valid input, i.e. an array. Normally a time to check to see if that item is an array. If the item
the answer is "yes", so you don't have to waste your is not an array, we put it into the res array. If it is an
time doing defensive programming. array, we use a spread operator ... to get all the items
5. Does the environment the code runs on has ES6+ out of it and put them back to the array.
support? The environment determines what
methods/native APIs you have access to.

Solutions
1 type ArrayValue = any | Array<ArrayValue>;
2
3 export default function flatten(value: Array<Array

Solution 1: Iterative Solution 4


5
const res = [];
const copy = value.slice();
First let's think through how we should check if a given 6
value is an array or not. We can use Array.isArray or 7 while (copy.length) {

instanceof Array to achieve that. There are some


8 const item = copy.shift();

nuances between these two. If you are interested you


9 if (Array.isArray(item)) {
10 copy.unshift(...item);
can check out this article by Jake Archibald. 11 } else {
12 res.push(item);
13 }
14 }
15 A recursion approach fits well here given the recursive
16 return res;
and nesting nature of this question. And it will simplify
17 }
our code a lot.
JavaScript TypeScript
Solution 2: Iterative Solution with
Array.prototype.some 1 /**

A more concise approach, compared to the previous one, 2 * @param {Array<*|Array>} value

is to use Array.prototype.some . 3
4
* @return {Array}
*/
5 export default function flatten(value) {
6 return value.reduce(
7 (acc, curr) => acc.concat(Array.isArray(curr)
1 type ArrayValue = any | Array<ArrayValue>;
8 [],
2
9 );
3 export default function flatten(value: Array<Array
10 }
4 while (value.some(Array.isArray)) {
5 value = [].concat(...value);
6 }
7
Although a recursive approach always has the risk
8
9 }
return value;
overflowing the call stack, as of this writing, in chrome,
the number of recursive calls you can make is around 10
thousands and in Firefox it is 50 thousands, so this
shouldn't be a problem in practice. However, when the
Solution 3: Recursive approach with cost of recursion becomes a concern, we can use a
Array.prototype.reduce

generator to lazily extract the flattened items from the 4 for (let i = 0; i < value.length; ) {

array. We will see that solution later. 5


6
if (Array.isArray(value[i])) {
value.splice(i, 1, ...value[i]);
7 } else {
Solution 4: Flatten the array in-place 8
9 }
i++;

All the solutions we have seen so far are returning a new 10 }


flattened array without mutating the original input array. 11
Again, this is normally what you want. 12 return value;
13 }
However, the interviewer might ask you to implement an
in-place solution that doesn't allocate extra memory.
That is, a solution with a constant O(1) space Solution 5: Recursive approaching using
complexity. flatMap
In this case, you will need to leverage array methods that The flatMap function method returns a new array
mutate. There are 9 methods in total that mutate arrays: formed by applying a given callback function to each
pop , push , reverse , shift , sort , splice , unshift ,
element of the array, and then flattening the result by
copyWithin and fill . one level. By calling it recursively, we can flatten the
Here is one possible solution that uses splice to mutate entire array until it is only one level deep.
the input array:
1 type ArrayValue = any | Array<ArrayValue>;
2
1 type ArrayValue = any | Array<ArrayValue>; 3 export default function flatten(value: Array<Array
2 4 return Array.isArray(value) ? value.flatMap((ite
3 export default function flatten(value: Array<Array
5 }

Solution 6: Generator
Bonus Solutions
As we have discussed earlier, if the array has a The following solutions only work under certain
thousands-of-levels nesting, a recursive approach might circumstances so they should not be used during
cause a stack overflow. We can utilize generators to yield interviews.
array item individually. As generators are lazy in nature,
this wouldn't have as big of an upfront cost as our Bonus Solution 1: Regex and
recursive approach does. JSON.stringify

Here is a solution that might be considered unorthodox:


we first encode the array into a JSON string via
1 /** JSON.stringify , and filter out brackets using regex /(\

[|\])/g , and we decode it back to an array using


2 * @param {Array<*|Array>} value

JSON.parse . Because all the brackets are stripped off


3 * @return {Array}
4 */
5 export default function* flatten(value: Array<any> with the regex, we end up with an array with only one
6 for (const item of value) { level of depth.
7 if (Array.isArray(item)) {
8 yield* flatten(item);
9 } else {
10 yield item; 1 type ArrayValue = any | Array<ArrayValue>;
11 } 2
12 } 3 export default function flatten(value: Array<Array
13 } 4 return JSON.parse('[' + JSON.stringify(value).re
5 }

There is a new flat array method added recently to the


JavaScript language. Obviously you cannot use this
Bonus Solution 2: toString when the array during interviews but it's still good to know that a native
contains only numbers flatten function is available in the language.
Recall that we asked about the data types as one of the
clarification questions? If the array contains only
numbers, here is a very simple solution: export default function flatten(arr) {
return arr.flat(Infinity);
}

1 function flattenOnlyNumbers(array) {
GFE 75 4/70 Mark complete
2 return array
3 .toString()
4 .split(',')
5 .map((numStr) => Number(numStr));
6 }

Note that this only applies when the array only contains
numbers, and this usage of toString might be thought
of as "obscure".

One-liner Solution with


Array.prototype.flat

You might also like