0

JSFiddle

The fiddle linked shows a function that uses recursion to flatten out an array of any dimension (thanks to users Bergi and Exlord for their help on the first part) and return the array with the highest index. I had a helluva time trying things before I could get something that worked. I'd like a couple things clarified:

  1. Is it code smell if you have an inner function inside a closure that explicitly accepts parameters? e.g:
  2. Why does the second script end with a maximum call stack size exceeded error?

-

return {
       data: flatten(array),
       rank: ranks.sort().reverse()[0]
       //smelly code?
 }

JS

   //working code block 
   (function () {
        function flattenAll(array) {
            var ranks = [];
            function flatten(array) {
                var rank = 0;
                var data = [];
                $.each(array, function (index, item) {
                    //recursion here
                    typeof (item) !== 'object' ? data.push(item) : data = data.concat(flatten(item));
                    rank++
                });
                ranks.push(rank);
                return data;
            };
            return {
                data: flatten(array),
                rank: ranks.sort().reverse()[0]
            }

        }
        console.log(flattenAll([3, 4, [[[[[[4]]]]]], [[1, 4, 5]], [4]]));
    })();
/****** second code block******************/
    (function () {
        function flattenAll(array) {
            var ranks = [],
                //tried different approach for returning data
                //this approach of setting returnData= data 
                //only grabs the last element in the array
                returnData = [];
            function flatten() {
                var rank = 0;
                var data = [];
                $.each(array, function (index, item) {
                    //recursion here
                    $.isArray(item) ? data = flatten(item) : data.push(item);
                    rank++
                });
                ranks.push(rank);
                returnData = data;
                return data;
            };
            return {
                data: flatten(), //no parens here vs the first code block
                rank: ranks.sort().reverse()[0]
            }

        }
        console.log(flattenAll([3, 4, [[[[[[4]]]]]], [[1, 4, 5]], [4]]));
    })();

Is there a proper way to handle handle recursion within closures? I'm not understanding everything that's going on here.

4
  • By 'rank' do you mean array length? Commented Feb 26, 2014 at 20:10
  • @thg435 rank is how many times array of array of arrays is true. So an array that has arrays in it, has a rank of 2. An array that contains an array of arrays of arrays has a rank of 3. Commented Feb 26, 2014 at 20:11
  • This is the correct usage of the term, but not what your code does. Commented Feb 26, 2014 at 20:20
  • @thg435 you're correct. it just so happened that my deepest array give me the same answer as the length of the array. Commented Feb 26, 2014 at 20:22

2 Answers 2

1

Maybe I'm missing something, but it looks like you're getting an infinite look in the second example because you're repeatedly calling flatten(item). flatten there does not take an argument. This means that you keep looping over the same array, which is the one you initially called flattenAll with, until you exceed the call stack allowance.

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

Comments

0

For the question about code smell, are you talking about the call to ranks.sort().reverse()[0]? If so, and you don't feel good about it, you could just maintain a reference to maxRank instead of all ranks.

Here's your second code block:

(function () {
    function flattenAll(array) {
        var ranks = [],
            //tried different approach for returning data
            //this approach of setting returnData= data 
            //only grabs the last element in the array
            returnData = [];
        function flatten() {
            var rank = 0;
            var data = [];
            $.each(array, function (index, item) {
                //recursion here
                $.isArray(item) ? data = flatten(item) : data.push(item);
                rank++
            });
            ranks.push(rank);
            returnData = data;
            return data;
        };
        return {
            data: flatten(), //no parens here vs the first code block
            rank: ranks.sort().reverse()[0]
        }

    }
    console.log(flattenAll([3, 4, [[[[[[4]]]]]], [[1, 4, 5]], [4]]));
})();

There's only one array variable, and it never changes. So the original array you call flattenAll with is the same one that's always operated on with $.each. Does that make sense, then, as to why you'd get a call stack exception? array points to the outer array because there's nothing hiding it.

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.