Creating a multi-dimensional array in JavaScript with two different sizes

I'm struggling to find the best way to create a multi-dimensional array with varying sizes dynamically.

Our user interface requires a pattern where there are rows of 4 items followed by rows of 3 items. This pattern should continue until all contents in the array have been used up.

This is essentially what I am trying to achieve:

// 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]];

The current code I have only converts the arrays into groups of 4 elements each.

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

I appreciate any help or guidance on how to achieve this. Thank you!

Answer №1

The solution provided below will modify the contents of 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) {                          // The loop continues as long as there are items in the array (the array size decreases with each iteration until it is empty)
  result.push(array.splice(0, i++ % 2 ? 3 : 4)); // Extract the first 3 or 4 numbers based on the value of index i (if i is even, cut 4 numbers; if odd, cut 3), then add them to the result array
}

console.log(result);

If you prefer not to alter the original array, you can utilize slice instead of splice, but specify the starting index for cutting:

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

let result = [], i = 0, next = 0;                      // 'next' indicates the index from which cutting begins
while(next < array.length) {                           // Loop while there are still items to be cut
  let itemsToCut = i % 2 ? 3 : 4;                        // Decide how many items to cut
  result.push(array.slice(next, next + itemsToCut));   // Cut items between 'next' and 'next + itemsToCut'
  next += itemsToCut;                                  // Increment 'next' by the number of cut-out items to point to the next item
  i++;
}

console.log(result);

Answer №2

Here is a more intuitive approach to generating a new array where the sizes of even and odd rows are determined by arguments provided:

function* generateNewArray(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 generateNewArray(array, 4, 3)) console.log(row);

To further refine the generateNewArray generator, we can start by implementing a simple repeat generator:

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

function* generateNewArray(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 generateNewArray(array, 4, 3)) console.log(row);

Answer №3

To achieve this task, utilize the Array#reduce method along with keeping track of the last position and a variable called step that toggles 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) { // check if previous sub-array is full
    r.push([]); // add new sub-array
    
    last = i; // mark current sub-array start index
    
    step = step === 4 ? 3 : 4; // alternate step value
  }
  
  r[r.length - 1].push(num); // push number to last sub-array
  
  return r;
}, []);

console.log(result);

Answer №4

Simple and clear-cut solution:

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

const finalArray = [];
let chunk = [];
let limit = 4;

array.forEach((element, index) => {
  if (chunk.length < limit) chunk.push(element);
  if (chunk.length === limit) {
    finalArray.push(chunk); 
    chunk = [];
    limit = (limit === 4) ? 3 : 4;
  }
})

console.log(finalArray)

Answer №5

Here's another clever solution that seems to be generating a lot of excitement.

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

function splitArray(array, index, count, result)
{
  if(array.length <= index) return result;
  result.push(array.slice(index,index+count));
  return splitArray(array, index+count, count === 4 ? 3 : 4, result);
}


console.log(splitArray(array, 0, 4, []));

Answer №6

Consider the analogy of slicing elements from an array in a loop, with a twist of alternating between 4 and 3 instead of using a constant value for the slice operation. To make this process more dynamic, we can parameterize the alternating values by passing them as arguments to a function rather than hardcoding them within the solution code:

  1. Utilize Array##slice method
  2. Implement a switch between current and next counts using destructuring assignment
  3. Adjust sub-array sizes (4,3) externally or incorporate flexibility by passing them as parameters to a function.

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));

Answer №7

Here's a unique approach to handling arrays where you can dynamically change the lengths of the inner arrays without much hassle.

Although the code could be more concise, I've kept it verbose for better readability.

// Defining a function that takes in:
//     an array
//     length of the first array
//     length of the second array
const arrayParser = (inArr,arr1len,arr2len) => {
    // Creating a new array.
    let outArr = [];
    // Using forEach loop to iterate over input array with index.
    inArr.forEach((val,idx) => {
        // Checking if the current index should start a new sub-array based on modulo operations.
        if (idx%(arr1len+arr2len)===0 || idx%(arr1len+arr2len)===arr1len) {
            // Adding a new empty array when needed.
            outArr.push([]);
        }
        // Appending value to the last sub-array in the output multidimensional array.
        outArr[outArr.length-1].push(val);
    });
    // Returning the resulting array.
    return outArr;
};

// Sample 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];
// Testing different configurations
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 method doesn't require calculating indexes as long as you know the lengths of the interior arrays beforehand.

Here's how a 4,3 setup plays out:

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

New arrays at indices 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

Result:

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

Answer №8

Despite its lack of elegance, I find myself resorting to a while loop when attempting to craft functional code...

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

let index = 0;
while (index < numbers.length) {
  let sectionFour = numbers.slice(index, index + 4)
  if (!(sectionFour.length > 0)) {
    break;
  }
  updatedNumbers.push(sectionFour)
  index += 4;
  let sectionThree = numbers.slice(index, index + 3);
  if (!(sectionThree.length > 0)){
    break;
  }
  updatedNumbers.push(sectionThree);
  index += 3;
}

return updatedNumbers

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular Igx-calendar User Interface Component

I need assistance with implementing a form that includes a calendar for users to select specific dates. Below is the code snippet: Here is the HTML component file (about.component.html): <form [formGroup]="angForm" class="form-element"> <d ...

What is the process for running "node server.js" within codelab?

I am currently going through a codelab tutorial on Bitbucket at this link After installing node.js for the first time, I encountered an error when trying to run the server.js file: node server.js The error message "node: Command not found" appeared even ...

Unable to properly connect my CSS file to the header partial

I am struggling to include my CSS file in the header partial Here is the link I am using: <link rel="stylesheet" href="stylesheets/app.css"> This is what my directory structure looks like: project models node_modules public stylesh ...

Waiting for an Element to Become Visible in Selenium-Webdriver Using Javascript

When using selenium-webdriver (api docs here), how can you ensure that an element is visible before proceeding? Within a set of custom testing helpers, there are two functions provided. The first function successfully waits for an element to exist, howeve ...

Tips for formatting strings to be compatible with JSON.parse

I'm encountering an issue with my node.js application where I am attempting to parse a string using JSON.parse. Here is the code snippet: try{ skills = JSON.parse(user.skills); }catch(e){ console.log(e); } The string stored in user.skill ...

Modifying an image's src using JavaScript is not possible

I'm attempting to modify the source of an image using a JavaScript function, but it doesn't seem to be working. The function is being executed within a mounted() method in Framework7. Here is my current setup: HTML: <div> <span> &l ...

Styling an active link in Next.js using Styled Components

Looking for a way to customize the active link style using styled components. I have a navigation bar where the currently active link should have a specific style applied. Any suggestions are appreciated! import React from 'react' import Link f ...

Is there a way to automatically override the CSS cursor style?

Issue with SCSS styling on image link I attempted to modify the cursor style from pointer to default, but after saving and reloading my React app, the change did not take effect. I tried writing some code, but it seems that Stack Overflow is indicating an ...

problem with the video pathway in the javascript document

I'm currently in the process of putting together a Video gallery playlist using HTML, CSS, and JavaScript. So far, I've set up the html and css files along with two js files. The first js file contains all the video information as shown here: ...

Bug causing repetition of matrix elements

I am facing difficulties in creating a matrix with the following structure: [0,1,2] [3,4,5] [6,7,8] Instead of getting the desired result, my elements are repeating. How can I resolve this issue? import numpy as np n = 3 X = np.empty(shape=[0, n]) for i ...

Utilizing ExpressJS to refresh database query after new record insertion

I'm a beginner in using expressJS and I have a question about querying the database (mongo in this case) to retrieve all records after adding one. exports.get = function (db) { return function (req, res) { var collection = db.get('n ...

Experiencing difficulties with JavaScript/jQuery when encountering the 'use strict' error

I have been working on a small function to change the background of an HTML file, but I keep getting the 'Missing 'use strict' statement' error message from JSLint despite trying multiple solutions. Can anyone suggest how to resolve th ...

Start the jQuery animation only when the ajax information differs

I am using setInterval to create a timer that runs every 20 seconds. It utilizes jQuery's ajax function load() to populate the toparticles div with data from another URL on the site. After the data is successfully loaded, it applies a jQuery highlight ...

Automatically scroll the page upon loading if the user is at the top of the page

Is there a way to trigger an action only when the page is detected to be at the very top, without executing it otherwise? I think maybe using an if statement could work, but I'm not entirely sure how to go about it. For instance, I'd like the pa ...

Do not ask for confirmation when reloading the page with onbeforeunload

I am setting up an event listener for the onbeforeunload attribute to show a confirmation message when a user attempts to exit the page. The issue is that I do not want this confirmation message to appear when the user tries to refresh the page. Is there ...

The process of updating UseContext global state in React Native and ensuring that the change is reflected across all screens

Struggling with updating global state values using React useContext on different screens? Attempting to change theme color in the App, but changes only appear on the current screen and not carried over to others? Looking for assistance in resolving this ...

What is the best way to access an excel file using JavaScript and Protractor?

Is it possible to read an Excel file dynamically in JavaScript and iterate through cell values using row and column counts, without converting it into a JSON object? I have searched through several posts on Stack Overflow but have not found a solution yet. ...

Why can my JavaScript server code read "2011" but not "20,11" when both are formatted as strings?

Currently, I am trying to establish a connection between Storm and JavaScript through redis. While the redis aspect of the connection is functioning correctly, I am encountering an issue when attempting to publish tuples (essentially Strings). Even though ...

Can you explain the difference between synchronous and asynchronous loading?

After exploring this website, I have learned that when using CommonJS, the browser loads files one by one after downloading them, which can lead to dependencies slowing down the process. However, with AMD, multiple files can be loaded simultaneously, all ...

WebPack bundling causing issues with Knockout Validation

I am developing a web application using Knockout along with the Knockout-Validation plugin, and I want to utilize WebPack for bundling. However, I encountered an issue where Knockout-Validation seems to break when incorporated with WebPack. To illustrate ...