我注意到Math::Cartesian::Product返回一个有福的对象而不是一个简单的数组数组。我无法弄清楚为什么。其实,我需要做一些额外的工作(unbless)使用结果...为什么Math :: Cartesian :: Product会返回祝福对象?
1
A
回答
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
是之前调用模块的结果。
如果由该模块返回的数据不符合您的需求,可以考虑从头开始编写操作,但执行笛卡尔产品操作不重要。
无论如何,检查模块源代码显示它不是太好。
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::Util
的reftype
。
'Set :: CrossProduct'是一个很好的选择。参见http://search.cpan.org/perldoc/Set::CrossProduct – 2010-12-13 13:40:37
作为对思南良好选择的平衡,有一个不好的选择:我的@cartesian = do {local $“=','; <{@ foo } {@ bar}>}; 如果你的数组包含glob元字符,这会快速分解,但不是它* fun *? – Hugmeir 2010-12-13 14:56:13