Как напечатать запятую "," в середине предложения при необходимости, часть 1, Perl - PullRequest
0 голосов
/ 13 ноября 2018

Мне нужно напечатать запятую "," если в списке больше одного, а если больше одного, то в последнем списке я не хочу печатать запятую. Я знаю, что могу использовать Join to, чтобы сделать это, но я не могу зациклить @NAMES запятой, если есть еще один @FAMILIES для добавления.

#!/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 голосов
/ 13 ноября 2018

Я подумал о вариации с икегами (сохранение результатов во временном массиве). Было бы слишком много изменений, чтобы было удобно помещаться в комментарии, поэтому здесь:

Вы также можете сохранить запятую во временном списке, а затем удалить ее только из последней строки.

#!/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;
}
0 голосов
/ 13 ноября 2018

Альтернатива состоит в том, чтобы отделить вывод от генерации кросс-продукта и специально обработать последний бросок.

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;
0 голосов
/ 13 ноября 2018

Я не вижу, что есть элегантный и чистый способ, так как вам нужно сбросить запятую на последнем элементе обоих массивов.Затем добавьте явное условие, перебирая индексы, чтобы можно было выделить последние элементы

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.

0 голосов
/ 13 ноября 2018

Специальный корпус, где последний элемент всегда грязный, есть куча компромиссов, вы просто выбираете, какой из них выглядит вам менее плохо.

Еще один вариант по сравнению с совершенно хорошим решением @ 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";
0 голосов
/ 13 ноября 2018

Использование 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) рекомендует использовать имена переменных с заглавными буквами только тогда, когда они являются константами.Это не имеет большого значения, и определенно не требуется, но это может немного облегчить для других возможность следовать вашему коду.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...