【问题标题】:Cartesian Product of two Strings两个字符串的笛卡尔积
【发布时间】:2013-06-05 19:34:48
【问题描述】:

我正在尝试在 Perl 中编写一个计算两个字符串的叉积(笛卡尔积)的函数。我在 Python 中有类似的代码,如下所示:

def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [a+b for a in A for b in B]

我怎样才能以优雅的方式模仿这个列表理解?

这是我目前所拥有的:

# compute the cross product of two Strings 
# cross('12','AB') = ((1,A), (1,B), (2,A), (2,B))
sub cross {
    # unpack strings
    my ($A, $B) = @_;

    # array to hold products 
    my @out_array;

    # split strings into arrays
    my @A_array = split(//, $A);
    my @B_array = split(//, $B);

    # glue the characters together and append to output array
    for my $r (@A_array) {
        for my $c (@B_array) {
            push @out_array, [$r . $c];
        }
    } 

    return \@out_array;
}

这并不完全符合我的预期,由于某种原因,引用来自 split() 而不是列表。

任何建议或其他更多优雅的笛卡尔产品解决方案将不胜感激。

【问题讨论】:

  • push @out_array, [$r . $c]; 将包含字符串的数组引用推送到@out_array。你不想要参考,所以跳过方括号。 split总是返回字符串,从不引用。
  • @amon 谢谢,我对这一点感到困惑。

标签: perl cartesian-product


【解决方案1】:

你的问题出在这部分:

push @out_array, [$r . $c];

$r . $c 将两个标量连接成一个字符串。 [EXPR] 创建一个数组引用。您不需要参考,只需简单的字符串:

push @out_array, $r . $c;

如果你不喜欢推送,而是语法糖,你可以使用一个实现收集/获取的模块:

my @cross = gather {
  for my $x (@A) {
    for my $y (@B) {
      take $x . $y;
    }
  }
};

这是实现的,例如List::GatherSyntax::Keyword::Gather

我自己也喜欢精致的map表达式:

my @cross = map { my $x = $_; map $x.$_, @B } @A;

(与forpush 相同)。


注意:Perl 没有与数组相关的“字符”概念。当需要单个字符时,它们由长度为 1 的字符串建模。Perl 数组总是包含标量,但出于(内存)性能原因,字符串不是作为 Perl 数组实现的,而是作为指向 C 数组(已知长度)的指针。缺点是字符串和数组的操作集不同,优点是内存使用量更少。

由于字符只是非常短的字符串,为了加入它们,我们使用标准字符串连接与.

【讨论】:

    猜你喜欢
    • 2015-08-08
    • 2023-03-17
    • 2018-04-04
    • 2012-01-03
    • 2017-03-05
    • 2020-08-23
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    相关资源
    最近更新 更多