Reputation: 979
The problem is to try and remove nested arrays:
steamrollArray([1, [2], [3, [[4]]]]); // should return [1, 2, 3, 4]
I have tried this but the recursion is failing when a nested array appears.
function checkElement(el) {
if (Array.isArray(el)) {
if (el.length === 1) {
return checkElement(el[0]);
} else {
for (var i=0; i < el.length; i++){
checkElement(el[i]);
}
}
} else {
return (el);
}
}
function steamrollArray(arr) {
var finalArr = [];
for (var i=0; i < arr.length; i++){
finalArr.push(checkElement(arr[i]));
}
return (finalArr);
}
Upvotes: 1
Views: 1289
Reputation: 561
A simpler solution without using any recursion is by using splice method of Arrays. It works for any level of nesting.
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]))
i--;
}
}
return arr;
}
Upvotes: 0
Reputation: 3536
I think this would be the funniest way to do this and also it's one line no more. Also it leaves extraction to native code which is much faster than Scripting.
var nestedArray = [1, [2], [3, [[4]]]];
var flatten = nestedArray.toString().split(',').map(Number);
console.log(flatten);
Upvotes: 2
Reputation: 20228
Using a generator function allows you to efficiently iterate through nested array elements without allocating unnecessary memory. If you really need the flattened array itself, use [...iterable]
or Array.from(iterable)
:
function* deepIterate(array) {
for (a of array) Array.isArray(a) ? yield* deepIterate(a) : yield a;
}
// Iterate through flattened array:
for (a of deepIterate([1,[2,[3]]])) console.log(a);
// Flatten array:
var flat = Array.from(deepIterate([1,[2,[3]]]));
console.log(flat);
Upvotes: 1
Reputation: 386570
A proposal for the first part:
You could change the return value to array and use concat instead of push.
function checkElement(el) {
// collect the values of the checked array
var temp = [];
if (Array.isArray(el)) {
if (el.length === 1) {
return checkElement(el[0]);
} else {
for (var i = 0; i < el.length; i++) {
// collect the values
temp = temp.concat(checkElement(el[i]));
}
// return flat values
return temp;
}
} else {
return el;
}
}
// this can be shorten to
function steamrollArray(arr) {
return checkElement(arr);
}
console.log(steamrollArray([1, [2], [3, [[4]]]]));
Part two, a bit shorter:
function steamrollArray(arr) {
return arr.reduce(function flat(r, a) {
return Array.isArray(a) && a.reduce(flat, r) || r.concat(a);
}, []);
}
console.log(steamrollArray([1, [2], [3, [[4]]]]));
Upvotes: 3
Reputation: 216
Try This if it work for you
function steamrollArray(unflatenArr) {
var flatenArr = [];
if (Array.isArray(unflatenArr)) {
for (var i = 0; i < unflatenArr.length; i++)
arrFlat(unflatenArr[i], flatenArr);
}
return flatenArr;
}
function arrFlat(arr, refArr) {
if (Array.isArray(arr)) {
for (var i = 0; i < arr.length; i++) {
arrFlat(arr[i], refArr);
}
}
else {
refArr.push(arr);
}
}
Upvotes: 0
Reputation: 2614
You could use reduce
:
function flatten( array ){
return array.reduce( function (a, b){
return a.concat( Array.isArray(b) ? flatten(b) : b );
}, [] );
}
Upvotes: 2
Reputation: 10450
You can use recursion like this:
function flatten(array) {
var flat = []; //The result array
//An IIFE that will perform the recursion,
//is equivalent to: function rec(param) {.....}; rec(param);
(function rec(a) {
//For each element in the array:
//If the element is an array then call the 'rec' function.
//Else, push it to the result array.
//I used the conditional (ternary) operator (condition ? expr1 : expr2 )
for(var i in a) Array.isArray(a[i]) ? rec(a[i]) : flat.push(a[i]);
})(array);//Initiate the recursion with the main array
return flat;//Return the final result
};
var a = [1, [2], [3, [[4]]]];
function flatten(array) {
var flat = [];
(function rec(a) {
for(var i in a) Array.isArray(a[i]) ? rec(a[i]) : flat.push(a[i]);
})(array);
return flat;
};
console.log(flatten(a));
Upvotes: 1
Reputation: 216
Try this:
function steamrollArray(unflatenArr){
return eval("["+(JSON.stringify(unflatenArr).replace(/\[/g,'').replace(/\]/g,''))+"]")
}
steamrollArray([1, [2], [3, [[4]]]]);
Upvotes: -1
Reputation: 382130
You can't just return the values, or it wouldn't work when you have arrays of length > 1.
Here's a solution:
function steamrollArray(arr, flattened) {
if (!flattened) flattened = [];
for (var i=0; i < arr.length; i++){
if (Array.isArray(arr[i])) {
steamrollArray(arr[i], flattened);
} else {
flattened.push(arr[i]);
}
}
return flattened;
}
console.log(steamrollArray([1, [2], [3, [[4]]]])); // should return [1, 2, 3, 4]
Upvotes: 0