【发布时间】:2012-02-23 22:27:11
【问题描述】:
还有其他关于这个inotherlanguages和其他non-lazyJavaScript versions的问题,但我没有找到惰性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
【问题讨论】:
-
好奇:你为什么问这个问题?
-
@RobW 因为我需要它却找不到它。具体来说,我的distinct color generator 正在获得使用 HSV 或 Lab 的能力,并以任意顺序迭代这些轴(这对算法有影响),我不想手写 12不同的 3-nested-for-loops 集。现在我已经写了它,我不相信我的实现是最优雅的。 :)
-
惰性笛卡尔积、幂集、排列和组合在 js-combinatorics 模块中实现:github.com/dankogai/js-combinatorics
标签: javascript