0

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;
}
6
  • Can the array be arbitrary deep nested? Commented Apr 23, 2016 at 14:02
  • yes it can ! why ? Commented Apr 23, 2016 at 14:05
  • 7
    var i = 0. Without var, i is a global variable, so every call to steamrollArray shares it and modifies it. Commented Apr 23, 2016 at 14:06
  • What about feeding the streamrollArray a scalar object like a float,etc. so nesting depth 0? Commented Apr 23, 2016 at 14:06
  • You are allocating too much useless arrays. Commented Apr 23, 2016 at 14:07

5 Answers 5

1

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());
}
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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;
}

Comments

0
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.

Comments

0

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"]]]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.