2009-08-11 26 views

Respuesta

39

Los paréntesis cambiar el contexto en el que el grep se evalúa a partir contexto escalar a la lista contexto. En el contexto escalar grep devuelve el número de veces que la expresión era verdadera. En el contexto de la lista, devuelve los elementos para los que la expresión era verdadera.

A continuación se destacan el contexto diferencia hace:

my $x = grep {/foo/} @array; # the number of things that match /foo/ 
my ($x) = grep {/foo/} @array; # the first thing that matches /foo/ 
my @foo = grep {/foo/} @array; # all the things that match /foo/ 
my (@foo) = grep {/foo/} @array; # all the things that match /foo/ 
+0

'scalar @ array' es el número de elementos en' @ array' –

1

grep devuelve una lista. Cuando coloca el nombre de la variable escalar entre paréntesis, Perl trata ese l-value completo como una lista, por lo que asigna el primer valor de la lista a esa variable.

Si tuviera otros escalares entre paréntesis, se obtendría los valores de segunda, tercera, etc de return array grep 's en ellos:

my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array; 
+3

grep devuelve una matriz. Pero solo en el contexto de la matriz. – innaM

+0

Y en contexto escalar devuelve el número de veces que la coincidencia fue verdadera, así que realmente no importa quién escalará la matriz. – Plutor

+1

@Plutor: los documentos dicen explícitamente qué 'grep' hace, por lo que no hay justificación para publicar una descripción inexacta. –

8

Los paréntesis proporcionan una list context para grep. grep devolverá realmente la lista de elementos para los que la expresión era verdadera y no solo la cantidad de veces que la expresión era verdadera.

+0

contexto de s/array/contexto de lista/ –

+0

Mucho mejor. Gracias. – innaM

+0

De nada. –

7

creo que busca first_index de List::MoreUtils:

use List::MoreUtils qw(first_index); 

# ... 

my $index = first_index { $_ eq $search_for } @array; 
5

La función grep se comporta de manera diferente en el contexto de lista y el contexto escalar. Esta documentado en perldoc -f grep:

Evalúa el bloque o expr para cada elemento de la LISTA (localmente establecer $ _ para cada elemento) y devuelve el valor de lista que consiste en aquellos elementos para los que la expresión evaluada true. En contexto escalar, devuelve la cantidad de veces que la expresión era verdadera.

Puede duplicar este por su cuenta con el mal llamado wantarray función:

sub my_grep { 
    my $sub = shift; 
    my @return; 
    for my $item (@_) { 
     push @return if $sub->($item); 
    } 
    return @return if wantarray; 
    return scalar @return; 
} 
1

Además, creo que el uso de grep sólo para encontrar el primer caso es un poco ineficiente ya que todavía tiene que caminar a través y ejecutar la devolución de llamada en cada elemento de la matriz. Especialmente si su matriz es larga, es mejor escribir un bucle o utilizar List :: MoreUtils como se mencionó anteriormente.

Cuestiones relacionadas