2010-12-13 27 views

回答

2

一種選擇是模塊Set::CrossProduct,這將產生普通,unblessed數組引用:

use Set::CrossProduct; 
my $iter = Set::CrossProduct->new([ \@foo, \@bar ]); 

while (my $tuple = $iter->get){ 
    ... 
} 

或一次獲得所有元組:

my @tuples = $iter->combinations; 
1

它通過祝福返回cartesian陣列,這樣,當一些代碼如下所示運行

$b = $cartesian $a1, $a2; 
$c = $cartesian $b, $a3; 

...它可以檢測到$b是之前調用模塊的結果。

如果由該模塊返回的數據不符合您的需求,可以考慮從頭開始編寫操作,但執行笛卡爾產品操作不重要。

無論如何,檢查模塊源代碼顯示它不是太好。

+2

'Set :: CrossProduct'是一個很好的選擇。參見http://search.cpan.org/perldoc/Set::CrossProduct – 2010-12-13 13:40:37

+1

作爲對思南良好選擇的平衡,有一個不好的選擇:我的@cartesian = do {local $「=','; <{@ foo } {@ bar}>}; 如果你的數組包含glob元字符,這會快速分解,但不是它* fun *? – Hugmeir 2010-12-13 14:56:13

4

我最近增加了一個cartesian功能List::Gen

  • cartesian CODE LIST_of_ARRAYREF

    cartesian計算任意數量的數組參考的笛卡爾積,每個參數可以是任意大小。返回發電機

    use List::Gen 'cartesian'; 
    my $product = cartesian {$_[0] . $_[1]} [qw/a b/], [1, 2]; 
    print "@$product"; # 'a1 a2 b1 b2' 
    

的「發電機」返回是一個懶惰的並列陣列當記者問他們,將產生的值。也有反覆和其他存取方法:

my $pairs = cartesian {@_} [qw/$ @ %/], ['a'..'z'], [1 .. 3]; 

while (my @tuple = $pairs->next) { # $pairs->reset; #$pairs->index = 5; ... 
    print @tuple, ', '; 
} 
# $a1, $a2, $a3, $b1, $b2, $b3, $c1, $c2, $c3, $d1, $d2, $d3, $e1 ... 

我不知道你將與工作組有多大,但優勢,使用上述方法是,對發電機的存儲需求保持O(1)

my $digits = cartesian {join '' => @_} ([0..9]) x 10; 

say for @$digits[10**9 - 3 .. 10**9 + 3]; 

# 0999999998 
# 0999999999 
# 1000000000 
# 1000000001 
# 1000000002 
# 1000000003 

它只計算6個元素的集合,並且什麼都不存儲。

正如你從例子中可以看到的,cartesian返回值本身是一個生成器對象,但該對象的後續返回值是無論CODEREF傳遞給cartesian回報。所以,如果你想數組引用,這是簡單的:cartesian {\@_} ...


另外,你所要做的應對祝福參考什麼額外的工作?除了什麼ref將返回,一個有福的數組仍然是一個數組。如果您正在基於參考類型編寫開關邏輯,則應使用Scalar::Utilreftype

相關問題