如何在需要的句子中间打印逗号“,”,第1部分,Perl

时间:2018-11-13 02:53:27

标签: perl

当列表不止一个时,我需要打印逗号“,”,如果不止一个,则我不想打印逗号。我知道我可以使用Join来执行此操作,但是如果要添加另一个@FAMILIES,则无法使用逗号循环@NAMES。

#!/usr/bin/perl
use strict;
use warnings;

my @NAMES       = qw(ALLIES BOBBY CAKRA);
my @FAMILIES    = qw(A B C);


foreach my $names (@NAMES)
{
       foreach my $families (@FAMILIES)
       {
       print "$names, // $families\n";
       }
}

预期结果:

ALLIES, // A
ALLIES, // B
ALLIES, // C
BOBBY, // A
BOBBY, // B
BOBBY, // C
CAKRA, // A
CAKRA, // B
CAKRA // C

5 个答案:

答案 0 :(得分:2)

我看不到有一种优雅简洁的方法,因为您需要将逗号放在两个数组的最后一个元素上。然后添加一个显式条件,同时遍历索引,以便能够挑选出最后一个元素

use warnings;
use strict;
use feature 'say';

my @names       = qw(ALLIES BOBBY CAKRA);
my @families    = qw(A B C);

for my $n (0..$#names) {
    for my $f (0..$#families) {
        say $names[$n], 
            ( ($n == $#names and $f == $#families) ?  ' // ' : ', // '),
            $families[$f];
    }   
}

三元运算符( ? : )条件下的括号必须具有优先级。另一种方法是使用&&而不是and,这样可以更紧密地绑定,但是我不想让代码依赖 具体的运算符。

语法$#ary用于@ary的最后一个元素的索引。

答案 1 :(得分:1)

通常使用join是最好的答案,但这仅在您要防止在行尾使用逗号时才有效。 (至少对于简单的答案,我确定您可以破解它。)

您可以在$#array_name循环中使用Perl的for变量来检查您是否位于两个列表的末尾,例如:

#!/usr/bin/perl
use strict;
use warnings;


my @names       = qw(ALLIES BOBBY CAKRA);
my @families    = qw(A B C);

for my $i (0..$#names) {
    for my $j (0..$#families) {
    print "$names[$i]" . ($i == $#names && $j == $#families ? ' ' : ', ') . "// $families[$j]\n";
    }
}

此外,还请注意样式:《 Perl样式指南》(尝试perldoc perlstyle)建议仅在使用全大写字母的变量名称为常量时使用它们。这没什么大不了的,而且绝对不是必需的,但是它可以使其他人更轻松地遵循您的代码。 :)

答案 2 :(得分:1)

特殊外壳的最后一个元素总是很杂乱,需要权衡取舍,您最终只能选择对您来说看起来不太坏的一个。

与@zdim的完美解决方案相比,这是另一种选择。

请注意,在执行过程中,我将更改@names和@families,需要进行更多的权衡,如果有问题,则可以轻松地复制数组。

#!/usr/bin/perl
use strict;
use warnings;

my @names       = qw(ALLIES BOBBY CAKRA);
my @families    = qw(A B C);

my $last_name = pop(@names);

foreach my $names (@names)
{
       foreach my $families (@families)
       {
           print "$names, // $families\n";
       }
}

my $last_family = pop(@families);

foreach my $families (@families)
{
       print "$last_name, // $families\n";
}

print "$last_name // $last_family\n";

答案 3 :(得分:1)

另一种选择是将输出与跨产品生成分开,并专门处理最后的演员表。

my @cross_product;
for my $n (0..$#names) {
    for my $f (0..$#families) {
       push @cross_product, [ $n, $f ];
    }   
}

if (@cross_product) {
   say "$_->[0], // $_->[1]" for @cross_product[0..@cross_product-2];
   say "$_->[0] // $_->[1]" for $cross_product[-1];
}

您甚至可以避免用尽以下所有内存:

use Set::CrossProduct qw( );

my $i = Set::CrossProduct->new([ \@names, \@families ]);
my $N = $i->cardinality;
say sprintf '%1$s%3$s // %2$d', $i->get(), $_?',':'' for -$N+1..0;

答案 4 :(得分:1)

我想到了池上的一个变种(将结果存储在一个临时数组中)。可能会有太多更改以至于无法容纳在评论中,所以在这里:

您也可以将逗号存储到临时列表中,然后仅将其从最后一行中删除。

#!/usr/bin/perl
use strict;
use warnings;

my @names         = qw(ALLIES BOBBY CAKRA);
my @families      = qw(A B C);
my @output_lines;

foreach my $name (@names) {
    foreach my $family (@families) {
        push @output_lines, [$name, ',', ' // ' . $family . "\n"];
    }
}

if (@output_lines) {
    $output_lines[-1][1] = '';  # remove comma from last line
    print map { @$_ } @output_lines;
}