Есть другие вопросы об этом в другие языки и другие не-ленивые версии 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