1

Math :: Cartesian :: Productは、単純な配列の配列ではなく、祝福されたオブジェクトの配列を返すことに気づきました。理由がわかりませんでした。結果を使用するには、実際に追加の作業を行う必要があります(ただし)...

4

3 に答える 3

4

最近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を使用する必要があります。

于 2010-12-14T03:46:31.730 に答える
2

1つの代替手段は、モジュールSet :: CrossProductです。これにより、通常の、祝福されていない配列参照が生成されます。

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

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

または、すべてのタプルを一度に取得します。

my @tuples = $iter->combinations;
于 2010-12-13T13:46:29.797 に答える
1

cartesian次のようなコードを実行すると、によって返される配列が祝福されます。

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

...$bモジュールへの以前の呼び出しの結果であることを検出できます。

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

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

于 2010-12-13T12:48:50.543 に答える