Recursion to flatten an array not working - javascript

I was working on the steamroller problem of free code camp. I came up with two solutions: one works perfectly [1, 2, 3, 4], but the other is giving [ 4 ].
The problem asks to write a function that flatten any sort of array.
my working code:
function steamrollArray(arr) {
newArr = [];
for (i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i]) === true) {
newArr = newArr.concat(steamrollArray(arr[i]));
} else if (Array.isArray(arr[i]) === false) {
newArr.push(arr[i]);
}
}
return newArr;
}
steamrollArray([1, [2], [3, [[4]]]]);
my not working code:
function steamrollArray(arr) {
newArr = [];
for (i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i]) === true) {
newArr.push(steamrollArray(arr[i]));
} else if (Array.isArray(arr[i]) === false) {
newArr.push(arr[i]);
}
}
return newArr;
}
steamrollArray([1, [2], [3, [[4]]]]);
Can anyone explain why the second code give only [4] ?

That happens because in first code, you are using
newArr = newArr.concat() in which you are assigning it to local variable. So, even in recursion, the state will be stored.
But in second code, you are using newArr.push() and in recursion, you are again declaring newArr=[];
That is the issue.

function steamrollArray(arr) {
// I'm a steamroller, baby
let newArr = arr.slice(); //newArr is a copy of arr
var result = []; //this is going to be the flatted array
checkArray(newArr, result);
return result;
}
function checkArray(myArray, resultedArray) {
//this function is a a recursion
return myArray.map(elt => {
if (!Array.isArray(elt)) {
//so this is a simple element, it is not an array, lets push it
resultedArray.push(elt);
return elt;
} else {
return checkArray(elt, resultedArray);
}
});
}
console.log(steamrollArray([1, {},
[3, [
[4]
]]
])); // should return [1, {}, 3, 4].
Comments in the code are helpful

Related

How do I split an array into odd and even numbers and place them into a matrix. What I did:

function evenAndOdd(array1){
const array1 = [1,2,3,4,5,6]
const odd = []
const even = []
for (let i=0; i<array1.length; i++){
if (i%2===0){
even.push(array1[i]);
}else {
odd.push(array1[i])
}
array1.push(odd)
array1.unshift(even)
}
return array1
}
This is what i got from my console log
/usercode/index.js:3
const array1 = [1,2,3,4,5,6]
^
SyntaxError: Identifier 'array1' has already been declared
I was expecting: array1 = [[2,4,6],[1,3,5]]
You can Also try this.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const matrix = splitOddEven(arr);
console.log("Odd numbers:", matrix[0]);
console.log("Even numbers:", matrix[1]);
function splitOddEven(arr) {
let odd = [];
let even = [];
for (let number of arr) {
if (number % 2 === 0) {
even.push(number);
} else {
odd.push(number);
}
}
return [odd, even];
}
The error is correct, you're defining array as input to your function as well as in the function body. It should be used like this:
const array1 = [1, 2, 3, 4, 5, 6]
const result = evenAndOdd(array1)
Next, your function modifies its input and returns it. I'm guessing you just want to get the result without changing the input. So we change it like so:
function evenAndOdd(array1) {
const odd = []
const even = []
for (let i = 0; i < array1.length; i++) {
if (i % 2 === 0) {
even.push(array1[i]);
} else {
odd.push(array1[i])
}
}
return [even, odd]
}
This runs, but the result is wrong. The output is [ [ 1, 3, 5 ], [ 2, 4, 6 ] ]. The reason is that you're checking whether the index is odd/even, but the check should be on the value in the input array. You can fix it like this:
if (array1[i] % 2 === 0) {
even.push(array1[i]);
} else {
odd.push(array1[i])
}
I would also change the name array1 to input just to make it a bit more obvious what the variable represents.
Putting everything together, the code should look like this:
function evenAndOdd(input) {
const odd = []
const even = []
for (let i = 0; i < input.length; i++) {
if (input[i] % 2 === 0) {
even.push(input[i]);
} else {
odd.push(input[i])
}
}
return [even, odd]
}
const input = [1, 2, 3, 4, 5, 6]
let result = evenAndOdd(input)
console.log(result)
As a bonus, I would rather write it using filters on the input instead of a for loop and messing with indexes
function evenAndOdd(input) {
const odd = input.filter(x => x % 2 !== 0)
const even = input.filter(x => x % 2 === 0)
return [even, odd]
}
There are some logical issues in your code:
You are redefining the input to your function
You are appending the odd and even arrays to the input in each iteration
console.log(evenAndOdd([1,2,3,4,5,6]));
function evenAndOdd(array1){
const odd = [];
const even = [];
for (let i=0; i<array1.length; i++){
if (i%2===0) {
even.push(array1[i]);
} else {
odd.push(array1[i])
}
}
return [odd, even];
}

Flatten an array [duplicate]

This question already has answers here:
Flatten array of multiple nested arrays without recursion - javascript
(9 answers)
Closed last year.
I want to flatten an array with javascript but without recurssion and without prebuilt function.
This is the code but it dose not flatten the whole array and i want to know what is wrong with my code
input : [1, [2], [3,8, [[4]],9],[5,6]]
output : [1, 2, 3, 8, 5, 6]
Code :
flat = function(array) {
const output = []
for (let i = 0; i < array.length; i++) {
if (typeof array[i] == 'number') {
output.push(array[i])
} else {
let arr = array[i]
let n = 0
while (n < arr.length) {
if (typeof arr[n] == 'number') {
output.push(arr[n])
n++
} else {
arr = arr[n]
n--
console.log(arr, n);
}
}
}
}
return output
}
It's possible to do, but it involves managing a stack yourself, manually:
const input = [1, [2], [3, 8, [[4]], 9], [5, 6]];
const result = [];
const stack = [{current: input, pos: 0}];
while (stack.length > 0) {
let {current, pos} = stack.pop();
if (pos < current.length) {
let item = current[pos++];
stack.push({current, pos});
if (Array.isArray(item)) {
stack.push({current: item, pos: 0});
} else {
result.push(item);
}
}
}
console.log(result);
This is what a recursive approach would do in the background, more or less. If your concern about recursion was that you don't like/understand it, not sure that you will find this one more likeable.

Clousure with recursive to iterate an array

I tried to do a recursive function with clousure, but dosent work.
I tried to add each single number from array to finally return [1,2,3,4,5,6,7,8] but just return me [1,2,5] something weird is I put a console.log inside of else it's print me all numbers.
Could you explain me why happens this
var array = [1, 2, [3, 4], 5, [6, [7, 8]]]; // --> 1,2,3,4,5,6,7,8
function recursiveArrayPrint(array) {
let resultado = []
return function iterator() {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
recursiveArrayPrint(array[i])()
} else {
console.log(array[i])
resultado.push(array[i])
}
}
return resultado
}
}
const test = recursiveArrayPrint(array);
console.log('test: ',test())
the bug in your program
resultado is declared inside of recursiveArrayPrint
inside iterator you call recursiveArrayPrint, which creates a new resultado each time
only the outermost resultado is returned
function recursiveArrayPrint(array) {
let resultado = [] // #1
return function iterator() {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
recursiveArrayPrint(array[i])() // #2
} else {
console.log(array[i])
resultado.push(array[i])
}
}
return resultado // #3
}
}
how to fix
function recursiveArrayPrint(array) {
// no need for resultado
function* iterator() { // use generator
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
yield *recursiveArrayPrint(array[i]) // yield
} else {
yield array[i] // yield, not console.log
// no need for resultado
}
}
// no need for resultado
}
return iterator()
}
const arr = [1, 2, [3, 4], 5, [6, [7, 8]]]
for (const x of recursiveArrayPrint(arr))
console.log(x)
1
2
3
4
5
6
7
8
we can do better
recursiveArrayPrint is not a good name. We've disentangled the console.log effect from the iteration and the caller is free to decide what to do with the output. We can just call it recursiveArray instead
Inner function iterator is a bit useless now. No need for this abstraction anymore
for loop with i is prone to off-by-one errors. We can write this in a clearer way using for..of loop
function* recursiveArray(array)
{ for (const x of array)
if (Array.isArray(x))
yield *recursiveArray(x)
else
yield x
}
const arr = [1, 2, [3, 4], 5, [6, [7, 8]]]
for (const x of recursiveArray(arr))
console.log(x)
If you are hoping to get the flattened array as a return value, JavaScript provides Array.from which turns any iterable into an array -
console.log(Array.from(recursiveArray(arr)))
[1,2,3,4,5,6,7,8]
not just for arrays
We can rename recursiveArray to traverse and it can operate as a generic function
Instead of assuming the first input is an array, we check isArray first and only then run the for..of loop. Otherwise simply yield the input
function* traverse(t)
{ if (Array.isArray(t))
for (const x of t)
yield *traverse(x)
else
yield t
}
const arr = [1, 2, [3, 4], 5, [6, [7, 8]]]
for (const x of traverse(arr))
console.log(x)
1
2
3
4
5
6
7
8
Writing robust functions will help you in the long run. traverse could easily be expanded to step through Objects now or other iterables. Now when non-array input is given, instead of an error, we get a sensible result -
for (const x of traverse(123))
console.log(x)
123
So what the recursiveArrayPrint function does, is that it creates a variable and returns a function that has closure over this variable. I think you get this part. The part that might confuse you, is that when you encounter an array, you call the recursiveArrayPrint function again, which will only create a new variable and return a new function that has closure over this variable, but this is in an entirely different scope.
It might make more sense to look at it this way.
var array = [1, 2, [3, 4], 5, [6, [7, 8]]]; // --> 1,2,3,4,5,6,7,8
function recursiveArrayPrint(array) {
let resultado = []
return function iterator() {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
// This is where a new closure is created, but with reference to another variable
let resultado1 = []
return function iterator1() {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
// This is where a new closure is created, but with reference to another variable
}
return resultado1
}
}
} else {
console.log(array[i])
resultado.push(array[i])
}
}
return resultado
}
}
const test = recursiveArrayPrint(array);
console.log('test: ',test())
I think what you intend to do is something more like this.
var array = [1, 2, [3, 4], 5, [6, [7, 8]]]; // --> 1,2,3,4,5,6,7,8
function recursiveArrayPrint() {
let resultado = []
return function iterator(array) {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
iterator(array[i])
} else {
console.log(array[i])
resultado.push(array[i])
}
}
return resultado
}
}
const test = recursiveArrayPrint();
console.log('test: ',test(array))
I think the main problem in your code is not just a difficulty in mastering the different elements of the JavaScript language or simply knowing how to play with the scope of variables for example.
No, it's just algorithmic, and that's arguably the hardest thing to do. We all fell into the trap of doing complicated things by trying in vain to make them simple.
It takes time to experience, to practice incessantly to accustom our brain to handling concepts in order to know how to put them together without fail.
Recursive solution:
const arr1 = [1, 2, [3, 4], 5, [6, [7, 8]]];
function recursiveflat(arr)
{
let res = []
for (let el of arr)
if (Array.isArray(el)) res.push(...recursiveflat(el) )
else res.push(el)
return res
}
console.log( JSON.stringify( recursiveflat( arr1 )))
.as-console-wrapper {max-height: 100%!important;top:0}
The idea of a closure as a recursive function seems incompatible to me, the only thing that can be done is to have a recursive function in a closure.
const arr1 = [1, 2, [3, 4], 5, [6, [7, 8]]]
, arr2 = ['a','b',[['c','d'],'e','f'],'g',['h',['i',['j'],'k'],'l'],'m']
function recursiveflatClosure(arr_in)
{
let resFLat = [] // global array is more efficient in this case
recursiveflat(arr_in) // builder
return ()=>resFLat // closure answer
function recursiveflat(arr)
{
for (let el of arr )
if (Array.isArray(el)) recursiveflat(el)
else resFLat.push(el)
}
}
let test1 = recursiveflatClosure( arr1 )
, test2 = recursiveflatClosure( arr2 )
console.log('test 1:', JSON.stringify( test1() ))
console.log('test 2:', JSON.stringify( test2() ))
.as-console-wrapper {max-height: 100%!important;top:0}
This is a somewhat strange requirement. It seems that the desired API is for a function that accepts a nested array and returns a function that returns the flattened version of it. It's unusual as generally we would not have any need for that intermediate function.
But we can update your code to get this to work. The biggest problem is that your internal recursive iterator function takes no argument. When you make a recursive call to it, there is no place to store the data you want to process. So let's make this accept an array argument:
function iterator(array) {
Now we note that this internal function is supposed to be recursive, but you're trying to call the outer function from inside. Let's call this instead:
if (Array.isArray(array[i])) {
iterator(array[i])
} else {
And now, we can't return that iterator function directly. We need to add a level of indirection, one that passes our original array into it.
function iterator(array) {
// ...
}
return function() {return iterator (array)}
Together, these make for what seems to be the smallest change to make your function work correctly:
const array = [1, 2, [3, 4], 5, [6, [7, 8]]]; // --> 1,2,3,4,5,6,7,8
function recursiveArrayPrint(array) {
let resultado = []
function iterator(array) {
for (let i = 0; array.length > i; i++) {
if (Array.isArray(array[i])) {
iterator(array[i])
} else {
console.log(array[i])
resultado.push(array[i])
}
}
return resultado
}
return function() {return iterator (array)}
}
const test = recursiveArrayPrint(array);
console.log('test: ',test())
.as-console-wrapper {max-height: 100% !important; top: 0}
However
This does not sound like a good idea. If you want a flattened version of an array, other answers and comments here suggest better ways, including better recursive solutions.
Moreover, recursion is a technique strongly associated with functional programming, and a fundamental tenet of functional programming is to avoid data mutation. But this solution is built around mutating your temporary array, resultado. I would look to the other answers for better ways of doing this.
A simple and clean flattening approach based on a reduce task and a recursively used reducer function ... no need of a closure either ...
function collectItemFlattened(list, item) {
return list.concat(
Array.isArray(item)
? item.reduce(collectItemFlattened, [])
: item
);
}
console.log(
[1, 2, [3, 4], 5, [6, [7, 8]]].reduce(collectItemFlattened, [])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

freecodecamp Challenges- Seek and Destroy

I am trying to solve this challenge Seek and Destroy. I can't figure out what is wrong. Any help ?
Seek and Destroy
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
This is the initial code below:
function destroyer(arr) {
// Remove all the values
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
This is my Code below:
function destroyer(arr) {
var letsDestroyThis = [];
var i =1 ; while (i<arguments.length) {
letsDestroyThis.push(arguments[i]);
i++;
}
for(var j=0 ; j< arguments[0].length; j++) {
for (var k= 0; k< letsDestroyThis.length; k++) {
if(arguments[0][j] === letsDestroyThis[k]){
arguments[0].splice(j, 1);
}
}
}
return arguments[0];
}
destroyer([2, 3, 2, 3], 2, 3);
Thanks in Advance!
You can create an array of all values that are supposed to be removed. Then use Array.filter to filter out these values.
Note: Array.splice will change original array.
function destroyer() {
var arr = arguments[0];
var params = [];
// Create array of all elements to be removed
for (var k = 1; k < arguments.length; k++)
params.push(arguments[k]);
// return all not matching values
return arr.filter(function(item) {
return params.indexOf(item) < 0;
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
function destroyer(arr) {
/* Put all arguments in an array using spread operator and remove elements
starting from 1 using slice intead of splice so as not to mutate the initial array */
const args = [...arguments].slice(1);
/* Check whether arguments include elements from an array and return all that
do not include(false) */
return arr.filter(el => !args.includes(el));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
This worked for me:
function destroyer(arr) {
// Remove all the values
var args = Array.from(arguments);
var filter = [];
for (i = 0; i < args[0].length; i++) {
for (j = 1; j < args.length; j++) {
if (args[0][i] === args[j]) {
delete args[0][i];
}
}
}
return args[0].filter(function(x) {
return Boolean(x);
});
}
console.log(
destroyer([1, 2, 3, 1, 2, 3], 2, 3)
);
//two ways of resolving the Seek and Destroy challenge on the FreeCodeCamp
//I was trying to simplify this code, please post your solutions, simplifying the code
//as much has its possible
function destroyer1 (arr){
//get array from arguments
var args = Array.prototype.slice.call(arguments);
args.splice(0,1);
for (var i = 0; i < arr.length; i++){
for(var j = 0; j < args.length; j++){
if(arr[i]===args[j]){
delete arr[i];
}
}
}
return arr.filter(function(value){
return Boolean(value);
});
}
//--------------------------------------
function destroyer(arr) {
// Remove all the values
//Get values from arguments of the function to an array, index 0(arr[0] will be "arr",
//rest of indexes will be rest of arguments.
var args = Array.from(arguments);
for (var i = 0 ; i < args[0].length; i++){
for (var j = 1; j < args.length; j++){
if(args[0][i] === args[j]){
delete args[0][i];
}
}
}
return args[0].filter(function(value){
return Boolean(value);
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
console.log(destroyer1([1,6,3,9,8,1,1], 3,1));
This is my Code:
function destroyer(arr) {
var argsBeRemove = [...arguments];
argsBeRemove.shift();
return arr.filter(val => {
return argsBeRemove.indexOf(val) == -1;
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Here is my version of Seek and Destroy. I assume that there are no zero elements in input (that assumption allows to pass the challenge). But that way I can make found elements equal zero and then just filter them out. It is pretty straight forward and no index mess when deleting elements in for loops.
function destroyer(arr) {
// Remove all the values
var args = Array.prototype.slice.call(arguments);
var temp = [];
temp = arguments[0].slice();
for (j = 1; j < args.length; j++) {
for (i = 0; i < arguments[0].length; i++) {
if (arguments[0][i] == arguments[j]) {
temp[i] = 0;
}
}
}
function isZero(value) {
return value !== 0;
}
var filtered = temp.filter(isZero);
return filtered;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments, 1);
return arr.filter(destroyNum);
function destroyNum(element) {
return !args.includes(element);
}
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Give this a shot, it is way less convoluted:
function destroyer(arr) {
// arr1 is equal to the array inside arr
var arr1 = arr.slice(arguments);
// arr2 becomes an array with the arguments 2 & 3
var arr2 = Array.prototype.slice.call(arguments, 1);
// this function compares the two and returns an array with elements not equal to the arguments
return arr1.concat(arr2).filter(function(item) {
return !arr1.includes(item) || !arr2.includes(item)
})
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
The accepted solution returns a new array, instead of removing the elements from the existing array.
This can be achieved efficiently by iterating the array in reverse and removing any elements matching any of the filter arguments.
function destroy(original, ...matches) {
if('length' in original) {
let index = original.length
while(--index > -1) {
if(matches.includes(original[index])) {
original.splice(index, 1)
}
}
}
return original;
}
const original = [1, 2, 3, 1, 2, 3]
destroy(original, 2, 3)
console.log(original);
My answer is similar to previous one, but I didn't use indexOf. Instead of that I checked the values in cycle, but compiler gives me a warning to not to declare function in cycle.
function destroyer(arr) {
// Remove all the values
var temp = [];
for (var i = 1; i < arguments.length; i++) {
temp.push(arguments[i]);
arr = arguments[0].filter(function(value) {
return ( value !== temp[i - 1]) ;
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
We can get the arguments behind the array, which are the number required to be removed and store them to a list. Then, we can just use a filter to filter out the numbers that needed to be removed.
function destroyer(arr) {
let removeList=[...arguments].slice(1);
return arr.filter(e=>removeList.indexOf(e)===-1);
}
I know isn't the shortest way to do it, but i think is the more simple to understand in an intermediate level.
function destroyer(arr, ...elements) {
var i =0;
while(i<=arr.length){ //for each element into array
for(let j =0; j<elements.length; j++){ //foreach "elements"
if(arr[i]==elements[j]){ // Compare element arr==element
arr.splice(i,1); //If are equal delete from arr
i--; //Check again the same position
j=0;
break; //Stop for loop
}
}
i++;
}
return arr;
}
console.log(destroyer(["possum", "trollo", 12, "safari", "hotdog", 92, 65, "grandma", "bugati", "trojan", "yacht"], "yacht", "possum", "trollo", "safari", "hotdog", "grandma", "bugati", "trojan"));
console.log(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3));
function destroyer(arr) {
let newArray = Array.from(arguments).splice(1)
return arr.filter(item => !(newArray.includes(item)))
}

Javascript fixing my flatten(array) function

I can not figure out why my code does not flatten out the nested arrays as indicated. I'd greatly appreciate some help here. I used a recursion to get to the actual value of the nested array. I tried to debug my code, and it seems to replace my results array every time the recursion takes place.
//Helper methods
function toType(obj){
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
function each(collection, callback){
if (Array.isArray(collection)){
for (var i = 0; i < collection.length; i++){
callback(collection[i], i, collection)
}
} else {
for (var i in collection){
callback(collection[i], i, collection)
}
}
}
//Flatten function
function flatten(array, isShallow=false, callback){
var results = [];
each(array, function(item){
if (!!isShallow && toType(item) === 'array'){
each (item, function(value){
results.push(value);
})
} else if (toType(item) !== 'array'){
results.push(item);
} else {
return flatten(item)
}
})
return results;
}
flatten([1, [2], [3, [[4]]]]);
// ---> [1]
Your problem appears to be with this line:
return flatten(item)
Returning here is a problem because the loop will end and the current entries in results will be ignored, as well as the remaining items. The line should be changed to instead append the results of
flatten(item)
to results array via push.
I recommend using a library for this sort of thing. http://underscorejs.org/#flatten is a great one!
Please see the refactored code below.
The major change is that instead of creating new copies of results, we are passing it to subsequent calls to flatten as a reference.
Please see the added comments
//Helper methods
function toType(obj){
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
function each(collection, callback){
if (Array.isArray(collection)){
for (var i = 0; i < collection.length; i++){
callback(collection[i], i, collection)
}
} else if(typeof collection === 'object'){
//type number was failing here
for (var i in collection){
callback(collection[i], i, collection)
}
}
else {
//default for primitive types
callback(collection, 0, collection);
}
}
//Flatten function
//Removed isShallow, how do we know if its shallow or not?
//Added results as arg, so we only manipulate the reference to results
//And to not create multiple scopes of var results;
function flatten(array, results, callback){
results = results || [];
each(array, function(item){
//removed 3rd if clause not needed.
//Only need to know if item is an object or array
if (toType(item) === 'array' || toType(item) === 'object'){
each (item, function(value){
flatten(value,results);
})
} else {
results.push(item);
}
})
return results;
}
var array1 = [1,[2,[3,4]]];
var array2 = [5,[6,[7,[8, {a:9,b:[10,11,12]}]]]];
var obj = {a:array1, b:array2};
console.log(flatten(array1)); // [ 1, 2, 3, 4 ]
console.log(flatten(array2)); // [ 5, 6, 7, 8, 9, 10, 11, 12 ]
console.log(flatten(obj)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
You can do something like that:
function flatten(array, i) {
i = i || 0;
if(i >= array.length)
return array;
if(Array.isArray(array[i])) {
return flatten(array.slice(0,i)
.concat(array[i], array.slice(i+1)), i);
}
return flatten(array, i+1);
}
Example:
var weirdArray = [[],1,2,3,[4,5,6,[7,8,9,[10,11,[12,[[[[[13],[[[[14]]]]]]]]]]]]]
flatten(weirdArray);
//returns ==> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
The best way to flatten you array in javascript is to use splice function of Array. Please follow the following code. It works for nesting as well.
function flattenArray(arr){
for(var i=0;i<arr.length;i++){
if(arr[i] instanceof Array){
Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
}
}
return arr;
}
Use underscore.js's flatten function (http://underscorejs.org/#flatten). Underscore.js is a 3rd party library with 80 some-odd functions to make your life as a javascript programmer easier. Don't reinvent the wheel.
var _ = require('underscore');
_.flatten([1, [2], [3, [[4]]]]);
=> [1, 2, 3, 4];

Categories

Resources