Get all possible options for a matrix in javascript
This can be a good interview question.
See JS Bin for running example.
getAllPermutations(newItem);function getAllPermutations(item) { var permutations = []; getAllPermutations0(item, permutations, []); console.log(permutations);}function getAllPermutations0(item, permutations, array) { if (array && array.length === item.Settings.length) { permutations.push(array.slice()); // The slice clone 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 }); getAllPermutations0(item, permutations, array); array.pop(); // pop the old one first }}
Here is a none recursive solution. It takes an empty or existing settings
"matrix" and a values
array, and return a new matrix as a combination of existing matrix content cloned for each new value, appended with pairs of new value setting items.
[A]
-> [1,2]
gives [A][1][A][2]
[A][1][A][2]
-> [X,Y]
gives [A][1][X][A][2][Y][A][2][X][A][1][Y]
and so on
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 now create the desired settings literal this way :
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 produces this :
[[{"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"}],[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}]]
You can use Array.prototype.map()
, for
loop, while
loop, Array.prototype.concat()
. Iterate gender
values; select each of color
, size
value in succession beginning at index 0
of either; iterating the furthest adjacent array from current gender
, increment the index of the closest adjacent array; merge the resulting two gender
arrays to form a single array containing all combinations of gender
, color
, 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>