Вопрос

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

Я пытаюсь объединить несколько значений в определенном порядке..Мой код выглядит примерно так..

my $separator = ":";
my @vals = qw(name last-name first-name phone);
my $return_name;
$return_name = map { 
    $return_name = $return_name . $query->param($_) . $separator 
} @vals;

То, что я получаю, - это "4", вместо объединения всех в одну строку.

То , чего я пытаюсь достичь , - это более короткая версия ...

$return_name = $query->param('name') . 
    $separator . $query->param('last-name') . 
    $separator . $query->param('first_name') . 
    $separator . $query->param('phone');

(На самом деле я пытаюсь собрать воедино около 25 $query->params.Я привел только четыре для краткости)

Это было полезно?

Решение

Часть вашей проблемы - это путаница в том, как map работает.

map принимает список аргументов, выполняет операцию над элементами списка и создает новый список из результатов.В скалярном контексте он возвращает количество элементов в новом списке.

В большинстве случаев вы не хотите выполнять задание в map операция.

# no assignment needed to set @foo
my @foo = map $_+2, 1,2,3; 
# @foo = (3,4,5);

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

Это объяснение не очень понятно.Ознакомьтесь с этими примерами, они должны помочь прояснить то, что я говорю.На первом показано, что карта может изменять значения, которые она обрабатывает:

my @foo = qw( fee fie foe fum );
my @bar = map { s/e/-/g } @foo;
# @foo = ( 'f--', 'fi-', 'fo-', 'fum' ); 
# @bar = ( 2, 1, 1, '' );

Чтобы избежать изменения @foo, вы можете сделать:

my @foo = qw( fee fie foe fum );
my @bar = map { my $val = $_; $val =~ s/e/-/g } @foo;
# @foo = ( 'fee', 'fie', 'foe', 'fum' ); 
# @bar = ( 'f--', 'fi-', 'fo-', 'fum' ); 

Или вы можете сделать:

список использований::Дополнительные утилиты qw( применить);

my @foo = qw( fee fie foe fum );
my @bar = apply { s/e/-/g } @foo;
# @foo = ( 'fee', 'fie', 'foe', 'fum' ); 
# @bar = ( 'f--', 'fi-', 'fo-', 'fum' );

На самом базовом уровне map работает как специализированная форма for петля.Два фрагмента кода дают точно такой же результат:

my @foo = map {$_ * 2} 1..5;

my @bar;
for (1..5) {
     my $val = $_ * 2;
     push @bar, $val;
}

Я надеюсь, что это помогло вам научиться думать о map.Как только вы научитесь использовать его (и связанные с ним конструкции, такие как grep и apply) вы сможете кратко выражать идеи, которые могут быть невероятно подробными при создании с использованием обычного циклического кода.

Другие советы

$return_name = map { $return_name = $return_name . $query->param($_) . $separator } @vals;

Это скалярное присвоение, которое придает операции map скалярный контекст.Карта в скалярном контексте возвращает количество элементов, которые были бы созданы.

В то время как эта конкретная строка кода взывает к использованию присоединиться(), если вы имеете опыт функционального программирования, вам может быть удобнее использовать reduce:

use List::Util 'reduce';
$return_name = reduce { $a . $query->param($b) . $separator } "", @vals;

map возвращает список, а не строку.Попробуй это:

$return_name = join $separator, map { $query->param($_) } @vals;

Или, если вы действительно хотите сократить количество строк, попробуйте следующее:

my $return_name = join ':', 
    map { $query->param($_) } 
    qw(name last-name first-name phone);

(Однострочная версия была вдохновлена ответом dsm.)

Попробуй это:

join $separator, 
     map { $query->param($_) } 
     ("name", "last-name", "first-name", "phone");

Чтобы ответить на причину, по которой вы получаете '4', это потому, что вы присваиваете результирующую мощность массивов скаляру.

В дополнение ко всем хорошим ответам, которые вы получили, обратите внимание, что

$return_name = $return_name . $query->param($_) . $separator;

может быть записан как

$return_name .= $query->param($_) . $separator;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top