繁体   English   中英

如何获得未知数量的数组中未知数量的元素的所有组合?

[英]How to get all combinations of unknown number of elements in unknown number of arrays?

我考虑了很多,并进行了搜索,但找不到答案:

我需要编写一个js函数,以获取具有未知数量数组的对象,而该数组又具有未知数量的元素。 像这样:

{
    Color: ["Color : Red", "Color : Blue", "Color : Green"], 
    Size : ["Size : S", "Size : M", "Size : L"], 
    Material : ["Material : Cotton"], 
    Something : ["Something : Anything", "Something : Anotherthing"]
}

同样,这可能是更多(或更少)的数组和元素,但是在这种情况下,我希望实现如下输出:

{0: "Color : Red > Size : S > Material : Cotton > Something : Anything",
 1: "Color : Red > Size : S > Material : Cotton > Something : Anotherthing",
 2: "Color : Red > Size : M > Material : Cotton > Something : Anything",
 3: "Color : Red > Size : M > Material : Cotton > Something : Anotherthing",
 4: "Color : Red > Size : L > Material : Cotton > Something : Anything",
 5: "Color : Red > Size : L > Material : Cotton > Something : Anotherthing",
 6: "Color : Blue > Size : S > Material : Cotton > Something : Anything",
 ...
 ...[and so forth... ]}

我试图在一个循环中做一个循环,但是失败了。 然后,我尝试首先找到最长的数组,从其余数组中提取出来,然后遍历最长数组中每个元素的每个数组:

createMap = function(tagObj, longest){

  var longObj = tagObj[longest];
  var current = {};

  delete tagObj[longest];

  $.each(tagObj, function(name, obj){
    $.each(obj, function(index, tag){
      $.each(longObj, function(i, iniTag){
        if (current[i]!= undefined){
          current[i] += " > " + tag; 
        }
        else current[i] = iniTag + " > " + tag;
      })
    })
  })
  console.log(current);
}

但这只会导致:

{0: "Color : Red, Size : S, Size : M, Size : L, .... "}

我希望我不仅能忽略一些显而易见的事情,而且我花了太多时间在上面,却无法解决。 现在我很紧张,无法思考了。 我非常感谢您的帮助! 提前致谢!

您可以使用多种计数器来做到这一点:首先,通过收集每个键及其元素数量,以及每个键的计数器。

作为一个数字底数(但底数根据数字而变化),我们增加下一个数字,如果该数字达到允许的最大数字,则将其放回0并增加下一个数字,依此类推。当每个数字都增加时我们已经完成了元素的完整循环。

function combinations(obj)
{
    var output = [];
    var meta = [], ml, cm;
    //ml: meta length
    //cm: current meta (in the while loop)

    for(var p in obj) if(obj.hasOwnProperty(p))
    {
        if(Object.prototype.toString.call(obj[p]) != '[object Array]')
            obj[p] = [obj[p]];
        meta.push({prop: p, len: obj[p].length, current: 0});
    }
    function addNow()
    {
        var add = {};
        for(var i = 0, l = meta.length; i < l; i++)
            add[meta[i].prop] = obj[meta[i].prop][meta[i].current]
        output.push(add);
    }
    cm = ml = meta.length - 1;
    while(cm >= 0)
    {
        addNow();
        cm = ml;
        while(cm >= 0 && ++meta[cm].current >= meta[cm].len)
        {
            meta[cm].current = 0;
            cm--;
        }
    }
    return output;
}

(见这个小提琴

您可以为此使用简单的递归解决方案:

function combine( obj ) {
  var keys = Object.keys(obj), combinations = [];

  // keys.sort(); // optional

  function rc(ki, combo) {
    var list;

    if (ki === keys.length)
      combinations.push(combo);
    else {
      list = obj[ keys[ki] ];
      for (var i = 0; i < list.length; ++i)
        rc( ki + 1, combo + " " + list[i] );
    }
  }

  rc(0, '');
  return combinations;
}

从起始对象的键列表和空结果数组开始。 请注意,对键进行排序以使结果以可预测的顺序返回可能是明智的,因为属性名称列表没有定义的顺序。

递归“ rc”函数从键数组的特定索引开始。 对于与该键相关联的数组中的每个字符串,该函数都会递归地调用自身以对下一个键进行操作,并通过将list元素附加到传入的字符串的末尾而形成一个基本字符串。当键列表耗尽时,每个完成的组合字符串都将附加到结果列表中。

通过调用第零个键“ rc”和一个空字符串作为起始值来启动该过程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM