【问题标题】:Get all possible options for a matrix in javascript在javascript中获取矩阵的所有可能选项
【发布时间】:2016-07-14 16:30:42
【问题描述】:

我在 JavaScript 中有一个“项目”对象,该项目可以有如下设置 颜色、大小等。

我需要在一个数组中获取所有可能的组合。

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

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

【问题讨论】:

    标签: javascript arrays json underscore.js permutation


    【解决方案1】:

    这可能是一个很好的面试问题。
    运行示例见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
        }
    }
    

    【讨论】:

    • 非常感谢,这不是采访,我被一个复杂的任务卡住了,谢谢兄弟!!!
    【解决方案2】:

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

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

    [A][1][A][2] -> [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)
    }
    

    演示 -> 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"}]
    ]
    

    【讨论】:

    • 这很好用,但我更喜欢另一个答案,因为它没有使用 JSON.parse(JSON.stringify(settings)),但是在弄乱了时间之后,我发现这种方式是 3快几倍,(可能只是 JSbin vs JSfiddle)
    • 嘿@CMS,我猜不是 - 脚本是在您的浏览器中执行的......我不知道,关于JSON.parse(JSON.stringify(settings)) 极其缓慢的神话可能有历史原因 - 无论哪种方式都获得 100%克隆是一项昂贵的任务。顺便说一句,我没有特别的理由使用 JSON.parse(JSON.stringify(settings)),只是我疯了似的知道我可以将其用作 oneliner。
    【解决方案3】:

    您可以使用Array.prototype.map()for 循环、while 循环、Array.prototype.concat()。迭代gender 值;从索引0 开始依次选择每个colorsize 值;从当前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)
    &lt;pre&gt;&lt;/pre&gt;

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

    【讨论】:

    • @CMS "如果另一个项目有其他设置,如宽度、颜色和...,这将不起作用。" 不确定解释“将不起作用”,“另一个项目有其他设置”正确吗?你能描述一下“不工作”和“另一个项目有其他设置”的意思吗?
    • 您对设置进行了硬编码,但每个项目都有不同的设置,前 2 个答案效果很好
    • 我让它与前 2 个答案一起工作,无论如何谢谢
    【解决方案4】:

    使用Array.prototype.reduce()Array.prototype.sort()Object.keys()for 循环、while 循环的方法

    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
    );
    &lt;pre&gt;&lt;/pre&gt;

    【讨论】:

      猜你喜欢
      • 2019-09-27
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 2022-01-21
      相关资源
      最近更新 更多