Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Generate Multidimensional array of 2 sizes

I cannot figure out the best way to dynamically generate a multidimensional array with 2 different sizes.

We have a UI that requires a row of 4 items, then 3. This pattern would repeat until the content in the array has been spent.

This is essentially what I need to do:

// Convert
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

// to
const rows [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14]];

This is what I currently have, it is only converting the arrays to 4 each.

 const buildRows = (arr, length) => arr.reduce((rows, val, i) => (
  i % length == 0 ? rows.push([val]) : rows[rows.length-1].push(val)
) && rows, []);

Thank you in advance for the help.

like image 769
Riley Bracken Avatar asked May 11 '17 21:05

Riley Bracken


People also ask

How do you create an array with two dimensions?

To declare a 2D array, specify the type of elements that will be stored in the array, then ( [][] ) to show that it is a 2D array of that type, then at least one space, and then a name for the array. Note that the declarations below just name the variable and say what type of array it will reference.

Can you create a 2 dimensional array with different types?

You can even create a two-dimensional array where each subarray has a different length or different type, also known as a heterogeneous array in Java. This means it's possible to create a two-dimensional array with variable column length in Java.

Are there 2D arrays in JavaScript?

Technically, there is no two-dimensional array in JavaScript. JavaScript supports 2D arrays through jagged arrays – an array of arrays.


2 Answers

The following solution will mutate (empty) the input array array:

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

let result = [], i = 0;
while(array.length) {                          // while there still items in array (array is continually getting shrunk untill it is emptied (array.length === 0))
  result.push(array.splice(0, i++ % 2? 3: 4)); // cut the first 3 or 4 numbers depending on the index of the cut i (if i is pair, then cut 4, else, cut 3) and then push the cut-out items into the result array
}

console.log(result);

If you don't want to mutate it, then use slice instead of splice, but you'll have to provide the start index of the cut:

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

let result = [], i = 0, next = 0;                      // next will be the index from which the cut will start
while(next < array.length) {                           // there is still items to cut
  let itemsToCut = i % 2? 3: 4;                        // determine how many items we are going to cut
  result.push(array.slice(next, next + itemsToCut));   // cut the items between next and next + itemsToCut
  next += itemsToCut;                                  // increment next by the number of cut-out items so it will point to the next item
  i++;
}

console.log(result);
like image 135
ibrahim mahrir Avatar answered Oct 07 '22 13:10

ibrahim mahrir


I suggest a more self-documenting generator solution where even & odd row-sizes are not hardcoded but supplied via arguments:

function* reshape(array, ...rows) {
  let i = 0;
  while (true) for (let row of rows) {
    if (i >= array.length) return;
    yield array.slice(i, i += row);
  }
}

// Example:
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
for (let row of reshape(array, 4, 3)) console.log(row);

A true generator purist would simplify reshape by first introducing a repeat generator:

function* repeat(iterable) {
  while (true) yield* iterable;
}

function* reshape(array, ...rows) {
  let i = 0;
  for (let row of repeat(rows)) {
    if (i >= array.length) break;
    yield array.slice(i, i += row);
  }
}

// Example: 
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
for (let row of reshape(array, 4, 3)) console.log(row);
like image 39
le_m Avatar answered Oct 07 '22 13:10

le_m