Javascript Generate a multidimensional array of 2 sizes

I cannot find a better way to dynamically generate a multidimensional array with two different sizes.

We have a user interface that requires a string of 4 elements, and then 3. This pattern is repeated until the content in the array is wasted.

This is basically 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 have at present, it is only converting 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.

+8
javascript arrays multidimensional-array
source share
8 answers

The following solution will mutate the (empty) input 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 do not want to mutate it, use slice instead of splice , but you need to specify the initial section index:

 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); 
+10
source share

I suggest a more self-documented generator solution where even and odd line sizes are not hardcoded, but delivered 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 purist generator 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); 
+7
source share

You can achieve this with Array#reduce , a pointer to the last place, and a step variable that alternates between 3 and 4:

 const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; let last = 0; let step = 0; const result = array.reduce((r, num, i) => { if(i === last + step) { // when the previous sub array is full r.push([]); // add another sub array last = i; // mark the start index of the current sub array step = step === 4 ? 3 : 4; // alternate the step } r[r.length - 1].push(num); // push the number to the last sub array return r; }, []); console.log(result); 
+3
source share

Straighfoward and easy to read solution:

 const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; const r = []; let chunk = []; let l = 4; array.forEach((el, i) => { if (chunk.length < l) chunk.push(el); if (chunk.length === l) { r.push(chunk); chunk = []; l = ( l === 4 ) ? 3 : 4; } }) console.log(r) 
+3
source share

Another solution. Clearly everyone is having a good time with this.

 const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; function divide(array, idx, num, result) { if(array.length <= idx) return result; result.push(array.slice(idx,idx+num)); return divide(array, idx+num, num === 4 ? 3 : 4, result); } console.log(divide(array, 0, 4, [])); 
+2
source share

We can consider it as cutting elements from an array in a loop. It's just that we need to alternate between 4 and 3 instead of a constant value for the slice. We can parameterize variable values ​​by passing them to functions instead of hard coding in the solution, as shown below:

  • Use Array##slice and
  • Just replace the current and the next like this, using destructuring assignment to achieve a solution.
  • Massive array sizes (4.3) can be changed outside of the actual logic or can be transferred to functions with a flexible solution.

 const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; function TransformArray(array, current, next) { let start = 0, ans = []; while (start < array.length - 1) { ans.push(array.slice(start, start + current)); start += current; [current, next] = [next, current]; //swap the count of array size } return ans; } console.log(TransformArray(array, 4, 3)); console.log(TransformArray(array, 3, 3)); 
+2
source share

Here's how to do it, I am expanding a bit to allow you to arbitrarily pass array lengths, this allows PM to change its mind at any time, and it doesn't really matter.

This can be cleaned a bit, I would like to leave it more detailed so that it is easier to read.

 // Setup the function getting in: // an array // first array length // second array length const arrayParser = (inArr,arr1len,arr2len) => { // Create a new array. let outArr = []; // Basic forEach is basic, we need the value and the index. inArr.forEach((val,idx) => { // If the index modulus of the total of the two array lengths is: // 0 OR the first array length // Push a new empty array. if (idx%(arr1len+arr2len)===0 || idx%(arr1len+arr2len)===arr1len) { // Create a new array with the current value outArr.push([]); } // Push the value to the last array in the out multidimensional array outArr[outArr.length-1].push(val); }); // You got it.. return the array. return outArr; }; // Single Dimensional Array const singleArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]; // Parse it. // Expects: // A Single Dimensional Array // Length of the first array // Length of the second array console.log(arrayParser(singleArray,10,4)); console.log(arrayParser(singleArray,2,4)); console.log(arrayParser(singleArray,3,4)); console.log(arrayParser(singleArray,4,3)); console.log(arrayParser(singleArray,1,2)); 

This works because you know the length of each of the internal arrays, so you do not need to figure anything out.

4.3 sets came out here.

 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Push a new array at 0 and 4. 4+3 index total Modulus 0 % 7 = 0 <-- push [], push 1 1 % 7 = 1 <-- push 2 2 % 7 = 2 <-- push 3 3 % 7 = 3 <-- push 4 4 % 7 = 4 <-- push [], push 5 5 % 7 = 5 <-- push 6 6 % 7 = 6 <-- push 7 7 % 7 = 0 <-- push [], push 8 8 % 7 = 1 <-- push 9 9 % 7 = 2 <-- push 10 10 % 7 = 3 <-- push 11 11 % 7 = 4 <-- push [], push 12 12 % 7 = 5 <-- push 13 13 % 7 = 6 <-- push 14 Returns [[1,2,3,4],[5,6,7],[8,9,10,11],[12,13,14]] 
+1
source share

It's ugly and as far as I'm trying to write functional code, it's pretty easy with a while loop ...

 const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; const newArray = []; let i = 0; while (i < array.length) { let four = array.slice(i, i + 4) if (!(four.length > 0)) { break; } newArray.push(four) i += 4; let three = array.slice(i, i + 3); if (!(three.length > 0)){ break; } newArray.push(three); i += 3; } return newArray 
0
source share

All Articles