2

Im new to programming, I have an assignment that asks to create a 2d-array from a 1d array. I came up with this (no help from any outside sources because it takes away the learning experience). It works for our professors test inputs, I was just wondering is this an ugly/inefficient solution.

function twoDArray(arr, lenSubArray) {
    var newArr = []; 
    var placeHolder = 0; 
    var leftOver = 0; 
    for (var i = 1; i < arr.length + 1; i++) {
        /* if i is a multiple of the specified sub-array size 
           then add the elements from placeHolder to i
        */
        if (i % lenSubArray === 0) {
            newArr.push(arr.slice(placeHolder, i)); 
            placeHolder += lenSubArray; 
            leftOver++; // tells us how many sub-arrays were created
        }
    }
    /* if original array is not divisible by the length of the specified sub-array
       then there will be left over values. Retrieve these values and create an 
       array out of them and add them to the 2d array.
    */
    if (!(arr.length % lenSubArray === 0)) {
         /* sub-array count multiplied by the length of each 
            sub-array gives us the right index to retrieve remaining values
        */
        leftOver = (leftOver * lenSubArray);
        newArr.push(arr.slice(leftOver))
    }

    return newArr; 
}

Test input: twoDArray([1, 2, 3, 4, 5], 3) output would be: [[1, 2, 3], [4, 5]]

Obito
  • 79
  • 9
  • please add an example of the input array and the wanted output array. – Nina Scholz Aug 20 '16 at 18:23
  • concat would give you a lot cleaner code. Check out this http://stackoverflow.com/questions/14824283/convert-a-2d-javascript-array-to-a-1d-array – AJ_ Aug 20 '16 at 18:25

3 Answers3

2

you're way too complicated:

  • create a result-array
  • push slices from i to i+lenSubArray
  • increment i by lenSubArray

and slice is smart enough to properly handle the end of the Array

function twoDArray(arr, lenSubArray) {
  var i = 0, result = [];
  while(i < arr.length)
    result.push( arr.slice(i, i+=lenSubArray) );
  return result;  
}
Thomas
  • 11,958
  • 1
  • 14
  • 23
1

You could use Array#reduce and build new arrays based on the index.

function twoDArray(array, length) {
    return array.reduce(function (r, a, i) {
        i % length ? r[r.length - 1].push(a) : r.push([a]);
        return r;
    }, []);
}

console.log(twoDArray([1, 2, 3, 4, 5], 3));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You do not need to iterate over an array. You can use Array.prototype.slice function instead.

function twoDArray(a, b){
    return (Array(Math.ceil(a.length / b)) + '').split(',').map(function(c, d){
        return a.slice(b * d, b * (d + 1));
    });
}

Here is how you call it

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
console.log(twoDArray(a, 3));
// Output:
// [
//   [1, 2, 3],
//   [4, 5, 6],
//   [7, 8, 9],
//   [10, 11, 12]
// ]
  • oh, that's not nice: if you calculate the length as `Math.ceil(a.length/b)` you don't have to patch the result by filtering, and instead of `(Array(len)+'').split(',').map(fn)` you can use `Array(len).fill(0).map(fn)` or `Array.from({ length: len }, fn)` – Thomas Aug 20 '16 at 18:45
  • @Thomas. Using `Math.ceil` is bad practice, it is better to convert second argument to integer and then filter array is necessary. Also, `Array.prototype.fill` is not implemented in some versions of Node.js. –  Aug 20 '16 at 18:48
  • why do you consider `Math.ceil` as bad, even worse, than creating two unnecessary Arrays and calling a filter-function on every element of the result? – Thomas Aug 20 '16 at 19:04
  • @Thomas. Because `Math.ceil` can produce `NaN` values if some error uccurs which can cause problems later. But anyway, I edited answer. –  Aug 20 '16 at 19:12