Reputation: 3
I am making the steamroller bonfire in freeCodeCamp I can't figure out why my code is not working and it only goes for the first element in an array
function steamrollArray(arr) {
// I'm a steamroller, baby
var flat = [];
for( i=0; i < arr.length; i++ ){
if( Array.isArray(arr[i]) ){
flat = flat.concat(steamrollArray(arr[i]));
} else {
flat.push(arr[i]);
}
} // end of the for loop
return flat;
}
Upvotes: 0
Views: 974
Reputation: 25
Here is my code,hope this helpful:
function steamrollArray(arr) {
let newArr = [];
//function:push every value in arr to newArr;
const getValue = function(elem) {
if(Array.isArray(elem)) {
elem.forEach(getValue);
}else{
newArr.push(elem);
}
}
arr.forEach(getValue);
console.log(newArr);
return newArr;
}
steamrollArray([[["a"]], [["b"]]]);
Upvotes: 0
Reputation: 352
function steamrollArray(arr) {
return String(arr).split(',').map(Number); }
If it works in all your cases, it works for the "flatten" example above, let me know if I missed something.
Upvotes: 0
Reputation: 66324
Side effects, ES6, you can achieve a deep flatten in an iterative pattern using .splice
function flatten(arr) {
let i = 0;
while (i < arr.length) {
if (Array.isArray(arr[i])) arr.splice(i, 1, ...arr[i]);
else ++i;
}
return arr;
}
e.g. usage
flatten([1, [2], [[3]], [4, [5, [6]]], [[[7], 8], 9]]);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
If you don't want side effects, .slice
before,
functon flatClone(arr) {
return flatten(arr.splice());
}
Upvotes: 1
Reputation: 11
try recurse the array in the following method, use res[] to save the result;
function steamrollArray(arr) {
var res=[];
function recurse(array)
{
for(var i = 0; i < array.length; i++)
{
if(!Array.isArray(array[i]))
res.push(array[i]);
else
recurse(array[i]);
}
}
recurse(arr);
return res;
}
Upvotes: 0
Reputation: 476594
As is commented by @Jonathan the problem is that you use a counter i
which is not declared in the function and thus global. As a result recursive calls will alter the i
of the caller, etc.
function steamrollArray(arr) { // I'm a steamroller, baby var flat = []; for(var i=0; i < arr.length; i++ ){ if( Array.isArray(arr[i]) ){ flat = flat.concat(steamrollArray(arr[i])); } else { flat.push(arr[i]); } } // end of the for loop return flat; }
A second challenge however is making the code more efficient in both time and memory. This can be done by limiting the amount of list construction to one. You can do this by using a concept called an accumulator: a variable you update through the recursive process. First we need to initialize the variable:
function steamrollArray(arr) { return steamer(arr,[]); }
In this case the accumulator is the result as well, and we initialize the result as an empty array. Evidently we still need to implement the steamer
function:
function steamer (arr,target) { if(Array.isArray(arr)) { var n = arr.length; for(var i = 0; i < n; i++) { steamer(arr[i],target); } } else { target.push(arr); } return target; }
What one does is passing the target through the recursive enumeration of the array tree. In case the value turns out to be a scalar (Array.isArray
returns false
) we add the element to the end of the target
; otherwise we perform a recursive call.
The last thing this function does is returning the target
, after the initial steamer
call, target
will be filled with all elements in the nested list.
The advantage is we do not need expensive concat
functions, but only use the push
function O(n) times. If we make abstraction of the processing time necessary to construct an array (assume push
works in O(1) time), the algorithm now works in O(n) time and memory with n the number of leaves in the list tree.
Upvotes: 0