Pregunta

Estoy tratando de reducir el número de líneas de código que estoy usando, pero estoy acabar con un problema bastante sencillo (aunque me está haciendo campaña ya que estoy empezando a envolver mi cabeza alrededor de las referencias)

Estoy intentando concatenar varios valores en un orden particular .. Mi código es el siguiente ..

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;

Lo que quiero decir es "4", en lugar de concantenating todo en una sola cadena.

Lo que estoy tratando de lograr es una versión más corta de ...

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

(En realidad estoy tratando de hilvanar unos 25 $query->params. Sólo le he dado cuatro por razones de brevedad)

¿Fue útil?

Solución

Parte del problema es la confusión sobre cómo funciona la map.

map toma una lista de argumentos, realiza una operación en los elementos de la lista y crea una nueva lista de los resultados. En contexto escalar devuelve el número de miembros en la nueva lista.

En la mayoría de los casos usted no quiere hacer una asignación en la operación map.

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

La asignación de un lugar donde tiene sentido es si es necesario utilizar una operación que normalmente cambiar el valor de $_, pero hay que preservar los argumentos para mapear sin cambios.

Esta explicación no es muy clara. Echa un vistazo a estos ejemplos, que deberían ayudar a aclarar lo que estoy diciendo. La primera muestra que MAP puede alterar los valores que procesa:

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 la alteración @foo que puede hacer:

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

O se puede hacer:

(Aplicar)

Lista uso :: MoreUtils 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' );

En la mayoría de sus obras básicas map como una forma especializada de un bucle for. Los dos trozos de código producen exactamente el mismo resultado:

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

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

Espero que esto le ha dado un poco de ayuda para aprender cómo pensar en map. Una vez que haya aprendido a usarlo (y construcciones relacionadas como grep y apply) usted será capaz de expresar de forma concisa las ideas que pueden increíblemente detallado cuando se construyó utilizando el código de bucle normal.

Otros consejos

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

Esto es una tarea de escalar, lo que le da el contexto mapa operación escalar. mapa en los retornos contexto escalar un recuento de los elementos que se habrían producido.

Mientras que la línea de código en particular clama por el uso de join () , si viene de un fondo de programación funcional, que puede ser más cómodo con reducir:

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

map devuelve una lista, no es una cadena. Prueba esto:

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

O si usted realmente quiere reducir el número de líneas, intente lo siguiente:

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

(La versión de una línea se inspiró en la respuesta de DSM.)

Prueba esto:

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

Para responder a la razón por la que obtiene el '4', es porque está asignando cardinalidad las matrices resultantes a un escalar.

Además de todas las respuestas que ha recibido buenas, nota que

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

se puede escribir como

$return_name .= $query->param($_) . $separator;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top