Pergunta

Estou tentando reduzir o número de linhas de código que estou usando, mas estou acabando com um problema bastante simples (embora esteja me sujando, já que estou apenas começando a envolver minhas referências)

Estou tentando concatenar vários valores em uma ordem específica .. meu código se parece com isso ..

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;

O que estou recebendo é "4", em vez de conceder tudo em uma corda.

O que estou tentando alcançar é uma versão mais curta de ...

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

(Na verdade, estou tentando reunir cerca de 25 $query->params. Eu só dei quatro por brevidade)

Foi útil?

Solução

Parte do seu problema é confusão sobre como map funciona.

map Faz uma lista de argumentos, executa uma operação nos elementos da lista e cria uma nova lista dos resultados. No contexto escalar, ele retorna o número de membros na nova lista.

Na maioria dos casos, você não deseja fazer uma tarefa no map Operação.

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

O único lugar onde a atribuição faz sentido é se você precisar usar uma operação que normalmente mudaria o valor de $_, mas você precisa preservar os argumentos para mapear inalterados.

Essa explicação não é terrivelmente clara. Confira esses exemplos, eles devem ajudar a esclarecer o que estou dizendo. O primeiro mostra que seu mapa pode alterar os valores que processa:

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

Para evitar a alteração de @foo, você pode fazer:

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' ); 

Ou você pode fazer:

Use List :: MoreUtils QW (Aplicar);

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

No seu mais básico map funciona como uma forma especializada de um for ciclo. Os dois pedaços de código produzem exatamente o mesmo resultado:

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

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

Espero que isso tenha lhe dado alguma ajuda para aprender a pensar sobre map. Depois de aprender a usá -lo (e construções relacionadas como grep e apply) Você poderá expressar concisa idéias que podem incrivelmente detalhadas quando construídas usando código de loop normal.

Outras dicas

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

Essa é uma atribuição escalar, que fornece o contexto escalar da operação do mapa.mapa No contexto escalar retorna uma contagem dos elementos que teriam sido produzidos.

Enquanto essa linha específica de código clama pelo uso de Junte(), se você vier de um fundo de programação funcional, poderá se sentir mais confortável com o Reduce:

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

map Retorna uma lista, não uma string. Experimente isso:

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

Ou se você realmente deseja cortar o número de linhas, tente o seguinte:

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

(A versão de uma linha foi inspirada na resposta do DSM.)

Experimente isso:

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

Para responder ao motivo pelo qual você recebe '4', é porque você está atribuindo a cardinalidade das matrizes resultantes a um escalar.

Além de todas as boas respostas que você recebeu, observe que

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

pode ser escrito como

$return_name .= $query->param($_) . $separator;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top