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);
}
-
1Not a duplicate: this specific question is about an unspecified depth, not about flattening an array of arrays.Denys Séguret– Denys Séguret2016年07月13日 11:03:56 +00:00Commented Jul 13, 2016 at 11:03
-
The values in unflatten array could be non-numeric as well?gurvinder372– gurvinder3722016年07月13日 11:31:51 +00:00Commented Jul 13, 2016 at 11:31
-
1Check this answer from a similar questionAndreas– Andreas2016年07月13日 11:39:34 +00:00Commented Jul 13, 2016 at 11:39
9 Answers 9
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]]]]));
2 Comments
You could use reduce:
function flatten( array ){
return array.reduce( function (a, b){
return a.concat( Array.isArray(b) ? flatten(b) : b );
}, [] );
}
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);
1 Comment
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));
2 Comments
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);
Comments
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]
Comments
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);
}
}
Comments
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;
}
Comments
Try this:
function steamrollArray(unflatenArr){
return eval("["+(JSON.stringify(unflatenArr).replace(/\[/g,'').replace(/\]/g,''))+"]")
}
steamrollArray([1, [2], [3, [[4]]]]);