1

I'm trying to create a function that puts each array element in its own array, recursively.

I think my base case is correct, but my recursive call doesn't appear to be working. any insight?

function ownList(arr){
  if (arr.length === 1) {
    arr[0] = [arr[0]];
    return;
  } else {
    return arr[0].concat(ownList(arr.slice(1)));
  }    
}
var arr = [1,2,3]
console.log(ownList(arr))// returns []
//should return [[1],[2],[3]]

Here I'm trying to put each pair in it's own list (recursive only). This code below is correct (update)

function ownListPair(arr){
  if (arr.length === 0)
    return arr;
  else if(arr.length === 1)
    return [[arr[0], 0]];
  else 
    return [[arr[0], arr[1]]].concat(ownListPair(arr.slice(2)));
}

// var arr = [3,6,8,1,5]
var arr = [2,7,8,3,1,4]
//returns [ [ 2, 7 ], [ 8, 3 ], [ 1, 4 ]]
console.log(ownListPair(arr))
12
  • Consider these 2 things: you're creating newArr each time you call the function, and one case does not return an array. If it's truly recursive, I would think any return should be of the same type. Commented Sep 8, 2015 at 14:28
  • @JoelEtherton Does the OP even need return newArr? you should only need that 1 return in the if because that is what is actually returning the finished array. Commented Sep 8, 2015 at 14:31
  • 3
    @devdropper87 it would be really helpful if you gave us some idea of what the desired outcome for this code is -- some sample input and desired output. Commented Sep 8, 2015 at 14:57
  • 1
    @lex82 No, I think that the clarification in the comments is ample to illustrate what the desired input/output it. But even if that is incorrect, you should not in my opinion edit questions this aggressively until it has been ascertained what it is that the author is asking, not editing + "Please tell me if I'm wrong". Clarify, don't assume. Commented Sep 9, 2015 at 7:48
  • 1
    @thomas. Yes, probably you are right. Actually I was hesitating first. However, when I saw that the author has already answered his own question, I decided it would be better to change the question to at least match his own answer to avoid further confusion and more wasted time from people trying to help. Anyway, the "Please tell me if I'm wrong" is certainly inconsistent with my action. Commented Sep 9, 2015 at 7:57

5 Answers 5

4

I prefer this solution for several reasons:

function ownList(a) {
  return a.length == 0
      ? []
      : [[a[0]]].concat(ownList(a.slice(1))) 
}
  • It's shorter and more concise
  • It works for empty arrays as well
  • The actual wrapping happens only once in the last line. Treating length == 1 separately -- as suggested by others -- is not necessary.
Sign up to request clarification or add additional context in comments.

3 Comments

thanks, love it and makes alot of sense. I'm trying to do something similar, but instead put pairs in their own list. if an element doesn't have a pair, add a zero in. I'm updating the code above. I'm so close! What am I doing wrong?
Your solution fails for arrays with an even number of elements. You will eventually run into the case that length is < 2 but then the array is empty and you are trying to access the first element.
Well then it works? If yes, please don't put the correct code in the question or make sure it is clear that it is solved now.
1

It would more appropriate to make a length of 0 be the null case. Then you just have to get the brackets right. The thing on the left side of the concat should be an array consisting of the array containing the first element.

function ownList(arr) {
  return arr.length ? [[arr[0]]].concat(ownList(arr.slice(1))) : [];
}

Here's an alternative, take your pick:

function ownList(arr) {
  return arr.length ? [[arr.shift()]] . concat(ownList(arr)) : [];
}

Using a bit of ES6 magic for readability:

function ownList([head, ...tail]) {
  return head === undefined ? [] : [[head]] . concat(ownList(tail));
}

Here the [head, ...tail] is using parameter destructuring which pulls the argument apart into its first element (head) and an array of remaining ones (tail).

Instead of concat you could also use the array constructor:

function ownList([head, ...tail]) {
  return head === undefined ? [] : Array([head], ...ownList(tail));
}

Comments

0

I think your basic assumption is wrong. What you need to do is check if each item in the array is an array, if not just add the item to the new array, if so have the function run itself on the array item.

That is recursion.

This code does that kind of recursion...

function ownList(arr)
{
    var newArr = [];
    var length = arr.length;

    for (var i = 0; i < length; i++) {
        if (typeof(arr[i]) === 'object') {
            newArr.push(ownList(arr[i]));
            continue;
        }

        newArr.push([arr[i]]);
    }

    return newArr;
}

var arr = [1, 2, 3];
console.log(ownList(arr));

Comments

0

Would something like this work:

var arr = [1, 2, 3, ["a", "b", "c", ["str"]]], 
result = [];

function flatten(input){

  input.forEach(function(el){
    if(Array.isArray(el)){
      flatten(el)
    }else{
      result.push([el]);
    }
  });

}

flatten(arr);
console.log(JSON.stringify(result));
//[[1],[2],[3],["a"],["b"],["c"],["str"]]

JSBIN

Edit:

var result = [];
function flatten(input){
  if (input.length === 0){
    console.log( "result", result ); //[[1],[2],[3],["a"],["b"],["c"],["str"]]
    return;
  }
  //if zeroth el of input !array, push to result
  if (!Array.isArray(input[0])){
    result.push(input.splice(0, 1));
    flatten(input);  
  }else{
    flatten(input[0]); //else, give input[0] back to flatten
  }
}

window.onload = function(){
  var arr = [1, 2, 3, ["a", "b", "c", ["str"]]];
    flatten(arr); 
}

JSBIN

2 Comments

that would technically work but not trying to take an iterative approach this is an exercise to make recursion more intuitive - I was told to try this without any for loops. Thanks for the suggestion :)
@devdropper87 I've added a solution that does not use loops. Is this more what you are looking for. I feel like I may be missing some of the criteria still, so I hope this is closer to what you are looking for..
0

After struggling through this today, turns out that this works :)

function ownList(arr){
  //base case:

  if (arr.length === 1) {
    return [arr];
  }

 //recurse
 //have to do two brackets here --> (arr.slice(0,1)) since length > 1
  return [arr.slice(0,1)].concat(ownList(arr.slice(1)));

}

var arr = [1,2,3]
console.log(ownList(arr))// returns [[1],[2],[3]]

2 Comments

This does not work with multiple layers of nested arrays which in your response to my comment you indicated was a requirement. [1, 2, 3, ["a", "b", "c", ["str"]]]; => [[1],[2],[3],[["a","b","c",["str"]]]]
This fails on ownList([]), because you have chosen a length of 1 to be the null case; a length of 0 would be better.

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.