0

I'm trying to understand how this snippet of codes work to flatten multi levels/nested array

can anyone please help to elaborate? thanks

var flatten = function(a, shallow,r){
  if(!r){ r = []}     //what does the exclamation mark mean here?...

if (shallow) {
  return r.concat.apply(r,a);  //I can't find what's .apply for concat method
  }

   for(var i=0; i<a.length; i++){
        if(a[i].constructor == Array){
            flatten(a[i],shallow,r);
        }else{
            r.push(a[i]);
        }
    }
    return r;
}

alert(flatten([1, [2], [3, [[4]]],[5,6]]));
4

3 Answers 3

5

Interestingly the shallow part of the code is not reached in the example.

update

I think the function is hard to follow. Here's an alternate that might be easier to read.

function flatten(arr) {

  var flatArray = [];

  function pushLoop(a) {
    var len = a.length;
    var i=0;
    for (i; i < len; i++) {
      if (a[i] && a[i].constructor == Array) {
        pushLoop(a[i]);
      } else {
        flatArray.push(a[i]);
      }
    }
  }

  pushLoop(arr);
  return flatArray;
}

original snippit

var flatten = function(a, shallow, r) {

  // if r does not exist create.
  if (!r) {
    r = []
  }

  // if shallow exists concat the arrays
  if (shallow) {

    // concat joins two or more arrays as paramenters.
    // The prototype apply allows us to define the parameters
    // as an array.  Esentially concat the arrays in array a.
    return r.concat.apply(r, a);
  }


  for (var i = 0; i < a.length; i++) {
    // Only flatten items that are arrays and push everything
    // else to the end.
    if (a[i].constructor == Array) {
      flatten(a[i], shallow, r);
    } else {
      r.push(a[i]);
    }
  }
  return r;
}

var output = document.getElementById("output");

var arr = (flatten([1, [2],
  [3, [
    [4]
  ]],
  [5, 6]
]));

output.innerHTML = JSON.stringify(arr);
<div id="output"></div>

Sign up to request clarification or add additional context in comments.

Comments

1

!r is a negation as in "Not r". It means that the if state meant will be true if r=false, r=null, or r=undefined.

.apply() is a member of all functions in javascript. It allows you to call the function with a different "this" scope than the function that it's in. Check this out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Comments

0

About Apply

The line return r.concat.apply(r,a) is misleading.

They could have used [].concat.apply(r,a) as well. 'apply' is a method defined on every object of type 'function' (typeof o === 'function', essentially any callable object) that executes the function with 'this' bound to the first argument and the arguments in the array passed as the second argument.

So let's say we have a function 'f'.

    function f(a,b,c) {
      this.x = a + b + c;
    }

These two code blocks both call f where this === objInstance and after both blocks are run, objInstance.x = 6.

    var Obj = function() {};
    Obj.prototype.f = f;
    var objInstance = new Obj();
    objInstance.f(1,2,3);

    var Obj = function () {};
    var objInstance = new Obj();
    f.apply(objInstance, [1,2,3]);

So [].concat.apply(r,a) is equivalent to [].concat applied with arguments a on the object r. It concatenates every array in a to the array r.

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.