Math :: Cartesian :: Productは、単純な配列の配列ではなく、祝福されたオブジェクトの配列を返すことに気づきました。理由がわかりませんでした。結果を使用するには、実際に追加の作業を行う必要があります(ただし)...
3 に答える
最近List::Gencartesian
に関数を追加しました:
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::Util
'sreftype
を使用する必要があります。
1つの代替手段は、モジュールSet :: CrossProductです。これにより、通常の、祝福されていない配列参照が生成されます。
use Set::CrossProduct;
my $iter = Set::CrossProduct->new([ \@foo, \@bar ]);
while (my $tuple = $iter->get){
...
}
または、すべてのタプルを一度に取得します。
my @tuples = $iter->combinations;
cartesian
次のようなコードを実行すると、によって返される配列が祝福されます。
$b = $cartesian $a1, $a2;
$c = $cartesian $b, $a3;
...$b
モジュールへの以前の呼び出しの結果であることを検出できます。
デカルト積操作を行うことは簡単なことです。そのモジュールによって返されるデータがニーズに合わない場合は、操作を最初から作成することを検討してください。
とにかく、モジュールのソースコードを調べると、それほど優れていないことがわかります。