关于此问题还有其他问题在其他语言以及其他非惰性的JavaScript版本,但我没有找到任何惰性的JavaScript版本。
给定一个由任意数量、任意大小的数组组成的数组:
var sets = [ [2,3,4,5], ['sweet','ugly'], ['cats','dogs','hogs'] ];
以及回调函数:
function holla( n, adj, noun ){
console.log( [n,adj,noun].join(' ') );
}
有没有一种优雅的方法可以迭代整个产品空间,而不必先创建一个所有可能组合的巨大数组?
lazyProduct( sets, holla );
// 2 sweet cats
// 2 sweet dogs
// 2 sweet hogs
// 2 ugly cats
// 2 ugly dogs
// 2 ugly hogs
// 3 sweet cats
// 3 sweet dogs
// 3 sweet hogs
// 3 ugly cats
// 3 ugly dogs
// 3 ugly hogs
// 4 sweet cats
// 4 sweet dogs
// 4 sweet hogs
// 4 ugly cats
// 4 ugly dogs
// 4 ugly hogs
// 5 sweet cats
// 5 sweet dogs
// 5 sweet hogs
// 5 ugly cats
// 5 ugly dogs
// 5 ugly hogs
请注意,这些组合与嵌套循环的结果相同:
var counts = [2,3,4,5];
var adjectives = ['sweet','ugly'];
var animals = ['cats','dogs','hogs'];
for (var i=0;i<counts.length;++i){
for (var j=0;j<adjectives.length;++j){
for (var k=0;k<animals.length;++k){
console.log( [ counts[i], adjectives[j], animals[k] ].join(' ') );
}
}
}
笛卡尔积的好处包括:
- 允许您嵌套任意数量的循环(也许您不知道要迭代多少项)
- 使您能够更改循环顺序(例如,首先按形容词循环),而无需编辑代码或编写所有可能的循环顺序组合。
基准测试
您可以在下面查看答案的基准测试:
http://jsperf.com/lazy-cartesian-product/26