为什么 Math::Cartesian::Product 返回受祝福的对象?

发布于 2024-10-07 08:12:50 字数 193 浏览 2 评论 0原文

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

I noticed Math::Cartesian::Product returns an array of blessed objects instead of a simple array of arrays. I couldn't figure out why. I actually need to do some extra work (unbless) to use the results...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

国际总奸 2024-10-14 08:12:50

我向 List::Gen 添加了一个 cartesian 函数最近:

  • 笛卡尔代码 LIST_of_ARRAYREF

    cartesian 计算任意数量的数组引用的笛卡尔积,每个数组引用可以是任意大小。返回一个生成器

    use List::Gen '笛卡尔';
    我的 $product = 笛卡尔 {$_[0] 。 $_[1]} [qw/ab/], [1, 2];
    打印“@$产品”; # '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)< /code>

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::Utilreftype

I added a cartesian function to List::Gen recently:

  • cartesian CODE LIST_of_ARRAYREF

    cartesian computes the cartesian product of any number of array refs, each which can be any size. returns a generator

    use List::Gen 'cartesian';
    my $product = cartesian {$_[0] . $_[1]} [qw/a b/], [1, 2];
    print "@$product"; # 'a1 a2 b1 b2'
    

The "generator" returned is a lazy tied array that will generate values when asked for them. There are also iterative and other accessor methods:

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 ...

I don't know how large the sets you will be working with are, but the advantage to using the above approach is that the storage requirements for the generator remain 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

which calculates only 6 elements of the set, and stores nothing.

As you can see from the examples, the return value of cartesian itself is a generator object, but that object's subsequent return values are whatever the coderef passed to cartesian returns. So if you want array references, it's as simple as: cartesian {\@_} ...


Also, what extra work did you have to do to deal with the blessed reference? A blessed array is still an array in every sense except for what ref will return. If you are writing switch logic based on reference type, Scalar::Util's reftype is what you should use.

蝶…霜飞 2024-10-14 08:12:50

一种替代方法是模块 Set::CrossProduct,它将产生普通的、未受祝福的数组参考文献:

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

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

或者一次获取所有元组:

my @tuples = $iter->combinations;

One alternative is the module Set::CrossProduct, which will yield ordinary, unblessed array references:

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

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

Or get all tuples at once:

my @tuples = $iter->combinations;
迷迭香的记忆 2024-10-14 08:12:50

它祝福由 cartesian 返回的数组,以便当运行如下所示的某些代码时

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

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

进行笛卡尔积运算是一件微不足道的事情,如果该模块返回的数据不符合您的需求,请考虑从头开始自己编写该运算。

无论如何,检查模块源代码会发现它并不太好。

It blesses the arrays returned by cartesian so that when some code as the following is run

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

... it can detect that $b is the result of a previous call to the module.

Doing a cartesian product operation is something trivial, if the data as returned by that module does not fit your needs, consider writting the operation yourself from scratch.

Anyway, inspecting the module source code reveals it is not too great.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文