2015-01-09 18 views
4

我是初学者,所以请原谅我的无知,如果这是微不足道的。通过循环未知数量的数组创建笛卡尔积(powerset?)

我有一个未知长度的javascript对象,每个属性的值都是一个数组(对我来说也是未知长度)。例如:

var obj = {"varA":[1,2,3], 
      "varB":['good','bad'], 
      "varC":[0,100], 
      "varD":['low','med','high'] 
      } 

我想遍历每个属性并为每个属性值组合创建一个新对象。如果我知道可以暴力破解的属性数量 - 强制使用for循环,但有没有办法在不知道有多少循环要硬编码的情况下枚举?

我基本上想要做这样的事情:

var oblist = []; 
for (a in varA){ 
for (b in varB){ 
    for (c in varC){ 
    for (d in varD){ 
    oblist.push({"varA":varA[a], "varB":varB[b], "varC":varC[c], "varD":varD[d]}); 
    } 
    } 
} 
} 

使oblist将包含类似的对象:

{"varA":1, "varB":"good", "varC":0, "varD":"low"} 
{"varA":1, "varB":"good", "varC":0, "varD":"med"} 
... 
{"varA":3, "varB":"bad", "varC":100, "varD":"high"} 

谢谢!

编辑: 看看我没有要求for循环或索引语法帮助。我在问如果我不知道对象中属性的数量(例如,varA,varB,varC,varD,varE,我可以拥有varZZ,我知道),我该怎么办,所以我不能只是坚硬代码4 for循环。有没有一种方法来设置使用obj [Object.keys(obj)[i]]。length?

+1

请显示您希望最终的输出数据结构看起来像您指定的'obj'输入。我没有遵循你想要的。 – jfriend00

+0

你的意思是你想要对象中每个数组的['power set'](http://en.wikipedia.org/wiki/Power_set)?如果是这样,那么这不仅仅是对象访问(@FelixKing)的重复。 – Xotic750

+4

嗨费利克斯,尊重你的代表和你已经链接到的答案的成功,我可以说我不认为这是一个骗局?要回答这个问题,你需要Object.keys,你的链接答案没有讨论过,还有一些逻辑将它们放在一起,以获得OP后面的组合。虽然人们经常因为询问Q版而被批评为SO,但实际上我认为这里有一个描述得很差但具体的挑战,你的优秀广泛答案实际上并没有涵盖。 – sifriday

回答

1

var obj = {"varA":[1,2,3], 
 
      "varB":['good','bad'], 
 
      "varC":[0,100], 
 
      "varD":['low','med','high'] 
 
      } 
 
    
 
// flatten the object into an array so it's easier to work with 
 
var obj2list = function(obj) { 
 
    var list = []; 
 
    for (var key in obj) { 
 
    if (obj.hasOwnProperty(key)) { 
 
     list.push({ 
 
     name: key, 
 
     val: obj[key] 
 
     }); 
 
    } 
 
    } 
 
    return list; 
 
}; 
 
    
 
// implement your favorite version of clone...this isn't particular fast 
 
var cloneObj = function(obj) { 
 
    return JSON.parse(JSON.stringify(obj)); 
 
} 
 
    
 
var iterateAndPopulateCombo = function(currentObj, listToIterate, result) { 
 
    if (listToIterate.length == 0) { 
 
    result.push(currentObj); 
 
    } else { 
 
    listToIterate[0].val.forEach(function(d) { 
 
     var newObj = cloneObj(currentObj); 
 
     newObj[listToIterate[0].name] = d; 
 
     iterateAndPopulateCombo(newObj, listToIterate.slice(1), result); 
 
    }) 
 
    } 
 
} 
 
    
 
var list = obj2list(obj); 
 
var result = []; 
 
iterateAndPopulateCombo({}, list, result); 
 
console.log(JSON.stringify(result)); 
 
document.body.appendChild(document.createTextNode(JSON.stringify(result)));

+0

不错。就在我在jsfiddle做我自己的版本时,我为你做了一个小提琴尝试 - 我认为我们有相同的结果,所以这是无论如何理解的问题!这是你的:http://jsfiddle.net/sifriday/udubdv5j/ – sifriday

+0

是的,你的结果是匹配的。 :) – Xotic750

1

你需要的组合技是你的OBJ内的所有阵列的cartesian product,这里显示的行动是一个小提琴:

http://jsfiddle.net/sifriday/qmyxhhny/2/

和代码.. 。

// I think the combo you're after is known as cartesian product 
// Here's a function to do it, from: 
// http://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript 
// It needs Underscore.js 
function cartesianProductOf() { 
    return _.reduce(arguments, function(a, b) { 
     return _.flatten(_.map(a, function(x) { 
      return _.map(b, function(y) { 
       return x.concat([y]); 
      }); 
     }), true); 
    }, [ [] ]); 
}; 

// Here's your object 
var obj = {"varA":[1,2,3], 
      "varB":['good','bad'], 
      "varC":[0,100], 
      "varD":['low','med','high'] 
      } 

// Now I extract the arrays from your object 
var idx, jdx, keys = Object.keys(obj), arrays = [], result1 = [], result2 = [] 
for (idx in keys) { 
    var key = keys[idx] 
    var arr = obj[key] 
    arrays.push(arr) 
} 

// We can calculate the combos of the obj, but this isn't annotated. 
result1 = cartesianProductOf.apply(null, arrays) 

// Now turn these back into annotated objects. 
for (idx in result1) { 
    var tmp = result1[idx], obj = {} 
    for (jdx in tmp) { 
     obj[keys[jdx]] = tmp[jdx] 
    } 
    result2.push(obj) 
} 

// Done! 
console.log(result2) 

经过一番努力,我认为可以整理一下;您可以确保注释在笛卡尔产品中发生。

+0

我为笛卡尔产品添加的链接是否符合您的想法?如果它确实存在,并且你有更好的标题,我相信我可以编辑它。 – Xotic750

+0

感谢您添加该链接 - 我正在阅读它!我想是这样。我认为它严格的涵盖在n元笛卡儿产品部分,它是4套产品。 – sifriday

+0

(这是你对权力集的评论让我想到了从集合论来解决这个问题) – sifriday