为什么Math :: Cartesian :: Product返回祝福的物体?

时间:2010-12-13 12:15:51

标签: perl cartesian-product bless

我注意到Math::Cartesian::Product返回一个受祝福的对象数组,而不是一个简单的数组数组。我无法弄清楚为什么。我实际上需要做一些额外的工作(unbless)才能使用结果...

3 个答案:

答案 0 :(得分:4)

我最近向List::Gen添加了cartesian功能:

  • 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'
    

返回的“generator”是一个惰性绑定数组,在被要求时会生成值。还有迭代和其他访问方法:

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的coderef返回的值。因此,如果您想要数组引用,它就像:cartesian {\@_} ...

一样简单

另外,你需要做些额外的工作才能处理受祝福的参考资料?除了ref将返回的内容之外,祝福数组在任何意义上仍然是一个数组。如果您根据参考类型编写开关逻辑,Scalar::Util的{​​{1}}就是您应该使用的。

答案 1 :(得分:2)

一个替代方案是模块Set::CrossProduct,它将产生普通的,未经过处理的数组引用:

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

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

或者立刻获得所有元组:

my @tuples = $iter->combinations;

答案 2 :(得分:1)

它保佑cartesian返回的数组,以便在运行以下某些代码时

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

...它可以检测到$b是之前调用模块的结果。

执行笛卡尔积产品操作是微不足道的,如果该模块返回的数据不符合您的需求,请考虑从头开始编写操作。

无论如何,检查模块源代码显示它不是太好。