Explore the myriad of choices available for a matrix in the realm of Javascript

In my JavaScript code, I have an object called 'item' which can have various settings such as color, size, etc.

My goal is to generate all possible combinations of these settings and store them in an array.

For example, let's take the following item:

var newItem = {
    name: 'new item',
    Settings: [
        {name: 'color', values: ['green', 'blue', 'red']},
        {name: 'size',  values: ['15', '18', '22']},
        {name: 'gender',values: ['male', 'female']}
    ]
};

I want to achieve something like this:

[
    [{SettingName:'color',value:'green'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
    // Remaining combinations...
]

Answer №1

Here's a great question for interviews!
Check out JS Bin to see this code in action.

generateAllCombinations(newItem);

function generateAllCombinations(item) {
    var combinations = [];

    generateAllCombinationsRecursive(item, combinations, []);
    console.log(combinations);
}

function generateAllCombinationsRecursive(item, combinations, array) {
    if (array && array.length === item.Settings.length) {
        combinations.push(array.slice()); // Cloning the array
        return;
    }

    var index =  array.length;
    var setting = item.Settings[index];

    for (var i = 0; i < setting.values.length; i++) {
        if (index === 0)
            array =  [];

        var currValue = setting.values[i];

        array.push({
            SettingName: setting.name,
            value: currValue
        });

        generateAllCombinationsRecursive(item, combinations, array);
        array.pop(); // Remove the last element from array
    }
}

Answer №2

Presented here is a non-recursive approach to solving the problem. This solution takes an empty or pre-existing "matrix" of settings and a values array as input, and returns a new matrix. The new matrix consists of cloned content from the existing matrix for each new value, along with pairs of new value setting items appended after each occurrence.

[A] -> [1,2] results in [A][1][A][2]

[A][1][A][2] -> [X,Y] yields

[A][1][X][A][2][Y][A][2][X][A][1][Y]

and so forth

function processSettings(settings, name, values) {
  if (settings.length == 0) {
    values.forEach(function(value) {
      settings.push( [{ SettingName: name, value: value }] )
    })
  } else {
    var oldSettings = JSON.parse(JSON.stringify(settings)), settings = [], temp, i = 0
    for (i; i<values.length; i++) {
      temp = JSON.parse(JSON.stringify(oldSettings))
      temp.forEach(function(setting) {
        setting.push( { SettingName: name, value: values[i] } )
        settings.push(setting)
      })
     }
   }
   return settings
}

You can generate the desired settings literal by following this method :

var settings = []
for (var i=0; i<newItem.Settings.length; i++) {
  var item = newItem.Settings[i]
  settings = processSettings(settings, item.name, item.values)
}

demo -> http://jsfiddle.net/b4ck98mf/

The above code snippet produces these results :

[
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
...

Answer №3

To achieve this, you have various options such as using Array.prototype.map(), a for loop, a while loop, or Array.prototype.concat(). Start by iterating through the values of gender, then select each color and size value in order starting from index 0 of either array. While iterating through the furthest adjacent array from the current gender, increment the index of the closest adjacent array. Finally, merge these two resulting gender arrays to create a single array with all combinations of gender, color, and size.

var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;

var res = [].concat.apply([], gen.map(function(value, key) {
  var next = -1;
  var arr = [];
  for (var curr = 0; curr < i; curr++) {
    while (next < i - 1) {
      arr.push([{
        SettingName: "gender",
        value: value
      }, {
        SettingName: "size",
        value: sizes[curr]
      }, {
        SettingName: "color",
        value: colors[++next]
      }])
    }
    next = -1;
  }
  return arr
}))

var newItem = {
  "name": "new item",
  "Settings": [{
    "name": "color",
    "values": [
      "green",
      "blue",
      "red"
    ]
  }, {
    "name": "size",
    "values": [
      "15",
      "18",
      "22"
    ]
  }, {
    "name": "gender",
    "values": [
      "male",
      "female"
    ]
  }]
}

var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;

var res = [].concat.apply([], gen.map(function(value, key) {
  var next = -1;
  var arr = [];
  for (var curr = 0; curr < i; curr++) {
    while (next < i - 1) {
      arr.push([{
        SettingName: "gender",
        value: value
      }, {
        SettingName: "size",
        value: sizes[curr]
      }, {
        SettingName: "color",
        value: colors[++next]
      }])
    }
    next = -1;
  }
  return arr
}))

document.querySelector("pre").textContent = JSON.stringify(res, null, 2)
<pre></pre>

Find the plnkr demo here http://plnkr.co/edit/C2fOJpfwOrlBwHLQ2izh?p=preview

Answer №4

Utilizing Array.prototype.reduce(), Array.prototype.sort(), Object.keys(), for loop, while loop

var newItem = {
    name: 'new item',
    Settings: [
    {
        name: 'color',
        values: ['green', 'blue', 'red']
    }, 
    {
        name: 'size',
        values: ['15', '18', '22']
    }, 
    {
        name: 'gender',
        values: ['male', 'female']
    }
    ]
};

var props = ["SettingName", "value"];
var settings = newItem.Settings;

function processData(settings, props) {
var data = settings.reduce(function(result, setting, index) {
  var name = setting.name;
  var obj = {};
  obj[name] = setting.values;
  result.push(obj);
  return result.length < index ? result : result.sort(function(a, b) {
    return a[Object.keys(a)[0]].length - b[Object.keys(b)[0]].length
  })
}, []);
var key = data.splice(0, 1)[0];
return [].concat.apply([], key[Object.keys(key)].map(function(value, index) {
  return data.reduce(function(v, k) {
    var keys = [v, k].map(function(obj) {
      return Object.keys(obj)[0]
    });
    var i = Math.max.apply(Math, [v[keys[0]].length, k[keys[1]].length]);
    var next = -1;
    var arr = [];
    for (var curr = 0; curr < i; curr++) {
      while (next < i - 1) {
        var a = {};
        a[props[0]] = keys[0];
        a[props[1]] = v[keys[0]][++next];
        var b = {};
        b[props[0]] = keys[1];
        b[props[1]] = k[keys[1]][next];
        var c = {};
        c[props[0]] = Object.keys(key)[0];
        c[props[1]] = value;
        arr.push([a, b, c]);
      };
      next = -1;
    }
    return arr
  });
}));
}

document.querySelector("pre").textContent = JSON.stringify(
  processData(settings, props), null, 2
);
<pre></pre>

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

JavaScript can be used to open several tabs simultaneously within a single browser window

Looking to open multiple tabs in the main browser? Check out this code snippet: function openSM() { window.open("http://www.google.com","_blank"); window.open("http://www.yahoo.com","_blank"); window.open("http://www.bing.c ...

Chrome runs requestAnimFrame at a smooth 60 frames per second, while Firefox struggles to keep up at

I recently developed a canvas animation using requestAnimFrame and saw great results in Chrome. However, when I viewed it in Firefox, it seemed like a slideshow was running instead of a smooth animation. I'm unsure what could be causing this issue. F ...

Dynamically attach rows to a table in Angular by triggering a TypeScript method with a button click

I need help creating a button that will add rows to a table dynamically when pressed. However, I am encountering an error when trying to call the function in TypeScript (save_row()). How can I successfully call the function in TypeScript and dynamically a ...

Arranging search findings based on relevance using javascript

I'm developing a personalized search feature. Currently, when I type "The R," the search results list starts with The Fellowship of the Ring because the phrase "the ring" is in its .text property. However, I want The Return of the King to appear first ...

Unable to retrieve variable declared externally from Switch Statement

Having an issue with assigning a value to the variable contactNumber inside a switch statement. Upon reaching the assignment line, an error SyntaxError: Unexpected identifier is triggered within the switch statement context. function contactMessageForCo ...

Methods for dynamically populating dropdown lists with JavaScript and Bootstrap

I have collected all 387 regions for the current date and now I want to dynamically populate a bootstrap dropdown with these regions using JavaScript. Below is the basic HTML code for a bootstrap dropdown: <div class="dropdown"> <button class ...

Controlling the Flow of Events in JavaScript Documents

Explore the integration of two interconnected Javascript files and delve into managing event propagation between them effectively. 1st js file var red = [0, 100, 63]; var orange = [40, 100, 60]; var green = [75, 100, 40]; var blue = [196, 77, 55]; var ...

Retrieving the current location synchronously via navigator.geolocation.getCurrentPosition();

I am having an issue with a function that is supposed to return the latitude and longitude as a string when called. Despite providing the correct values for latitude and longitude when alerting, it returns undefined. I would greatly appreciate any assist ...

Teaching jQuery selectors to detect recently-added HTML elements

Unable to find a solution in the jQuery documentation, I am seeking help here for my specific issue. Embracing the DRY principle, I aim to utilize JavaScript to include a character countdown helper to any textarea element with maxlength and aria-described ...

Retrieving User Activity Reports for a specified set of users within G Suite

I am currently attempting to utilize the Admin SDK Reports Service to retrieve the latest login time and other data for a specific set of 20 users. Due to the large size of the domain, it is not practical to fetch data for the entire domain and then filter ...

How can you make the browser window scroll horizontally when a div is clicked using jQuery?

I have an image of an arrow inside a div. The div is positioned fixed in the bottom right corner of an extremely wide page. Is there a way to utilize jQuery to scroll the window 600px to the right each time the arrow is clicked? Also, can I detect when th ...

Utilize various date fields within a JSON object to compare and incorporate them into a where clause for

I have a JSON structure stored in my Postgres 10.8 database with a text field. The structure looks like this: { "code_cd": "02", "tax_cd": null, "earliest_exit_date": [ { "date": "2023- ...

pausing a timer using JavaScript or jQuery

My goal is to make my clock stop at zero and then display the results page. Unfortunately, I am currently facing difficulties in achieving this. var clock = { time: 2, timeleft: 0, bigben: null, countDown: function() { clock.time--; $("#timer") ...

jqGrid doesn't refresh after making an AJAX request

I'm encountering an issue when trying to refresh a jqgrid. Despite attempting various solutions, I have yet to find one that works. My goal is to refresh the grid after receiving JSON data from the server side. Below is the code snippet showcasing how ...

Is there any other factor aside from the lack of a CSRF token in an AJAX request with Django that could lead to a 403 error?

The primary reason behind the django + ajax 403 error is usually the absence of a csrf token. However, in my scenario, the csrf token is present and a similar ajax function is working fine. I will also provide the backend view function that handles the res ...

Utilizing JavaScript to implement an interactive :hover pseudo-class dynamic effect

After reviewing a question on adding a hover class to an element, I am now curious about how to do the opposite. I already have a main class for a button I am planning to create, where I will customize the background for each button using myButton.style.b ...

The error "Element type is invalid" is being thrown by the <NavigationBar/> component in the App.js

I'm facing an issue with my NavigationBar in my React website. I've created a NavigationBar.js file and imported it into my App.js, but when I include the > <NavigationBar/> in my App.js, I encounter this error: Error message screensh ...

Unable to retrieve any data from cURL response, continuous no value output received

What is my goal: My objective is to receive a response from a webserver and extract some data from it. I have successfully received the response from the webservice. The issue at hand: Although I am able to retrieve the data response from the server using ...

Compare two strings in C#, sort them, and then store them in an array

Hey, I'm currently working on formulating my question better. Within the foreach loop, I am extracting values from an array and storing them in a temporary variable. These values come from the cells of a datagridview. In the subsequent for loop, I n ...

Leverage the Google Drive API for the storage of app-specific data

I'm currently developing a JavaScript application that runs on the client side and need to store a JSON object containing configuration details in a Google Drive Appdata file. Through the Google Drive API, I can successfully check for the file within ...