在javascript中获取矩阵的所有可能选项

时间:2016-03-27 07:39:28

标签: javascript arrays json underscore.js permutation

我在JavaScript中有一个'item'对象,该项可以有类似的设置 颜色,大小等

我需要在数组中获得所有可能的组合。

所以我们假设我们有一个看起来像这样的项目:

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

我需要以某种方式得到这个:

[
    [{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'}]
]

4 个答案:

答案 0 :(得分:6)

这可能是一个很好的面试问题 有关正在运行的示例,请参阅JS Bin

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
    }
}

答案 1 :(得分:2)

这是 none 递归解决方案。它需要一个空的或现有的settings“矩阵”和一个values数组,并返回一个新矩阵,作为为每个新值克隆的现有矩阵内容的组合,并附加成对的新值设置项。

[A] - &gt; [1,2]提供[A][1][A][2]

[A][1][A][2] - &gt; [X,Y]提供[A][1][X][A][2][Y][A][2][X][A][1][Y]

等等

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
}

您现在可以通过以下方式创建所需的设置:

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

演示 - &gt;的 http://jsfiddle.net/b4ck98mf/

以上产生了这个:

[
[{"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"}]
]

答案 2 :(得分:0)

您可以使用Array.prototype.map()for循环,while循环,Array.prototype.concat()。迭代gender值;从两个索引color开始连续选择size0值中的每一个;从当前gender迭代最远的相邻数组,增加最近的相邻数组的索引;合并生成的两个gender数组,以形成包含gendercolorsize

的所有组合的单个数组
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>

plnkr http://plnkr.co/edit/C2fOJpfwOrlBwHLQ2izh?p=preview

答案 3 :(得分:0)

使用Array.prototype.reduce()Array.prototype.sort()Object.keys()for循环,while循环

的方法

&#13;
&#13;
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 p(settings, props) {
var data = settings.reduce(function(res, setting, index) {
  var name = setting.name;
  var obj = {};
  obj[name] = setting.values;
  res.push(obj);
  return res.length < index ? res : res.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(
  p(settings, props), null, 2
);
&#13;
<pre></pre>
&#13;
&#13;
&#13;