2010-12-13 9 views

答えて

2

1つの選択肢は、通常、blessされていない配列参照が得られるモジュールSet::CrossProduct、次のとおりです。

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

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

あるいは、一度にすべてのタプルを取得:

my @tuples = $iter->combinations; 
1

それはcartesianによって返された配列を祝福...結果を使用する(unbless)いくつかの余分な作業を行う必要があるので、次のようにいくつかのコードが実行されると

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

...それを前回のモジュール呼び出しの結果であることを検出することができます。

デカルト積の演算を行うのは簡単ですが、そのモジュールから返されたデータがニーズに合わない場合は、最初から操作を書き込むことを検討してください。

とにかく、モジュールのソースコードを調べると、それほど大きくないことがわかります。

+2

'Set :: CrossProduct'は良い選択肢です。http://search.cpan.org/perldoc/Set::CrossProduct –

+1

を参照してください。Sinanの良い選択肢と相殺されて、代わりに悪い選択肢があります:my @cartesian = do {local $ "= '、'; {{@ foo } {@ bar}>}; 配列にglobメタキャラクタが含まれていても、これは高速ではありますが、それは* fun *ではありませんか? – Hugmeir

4

を私は最近List::Gencartesian機能を追加しました:

  • cartesian CODE LIST_of_ARRAYREF

    は任意の数の配列参照の任意の数のデカルト積を計算します。返された「発電機」は彼らのために尋ねられたときの値を生成します怠惰tieされた配列である発電機

    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自体はジェネレータオブジェクトですが、そのオブジェクトの後続の戻り値は、渡されたコードリファレンスがcartesianになっても返されます。あなたは配列参照をしたいのであれば、それは同じくらい簡単です:cartesian {\@_} ...また


、あなたは祝福された参照に対処するために行うために余分なものを仕事を持っていましたか? blessed配列はまだrefが返す以外のすべての意味で配列です。参照タイプに基づいてスイッチロジックを作成する場合は、Scalar::Utilreftypeを使用する必要があります。

関連する問題