2010-04-15 15 views
7

No entiendo la última línea de esta función desde Programming Perl 3e.¿Cómo funciona este Perl grep para determinar la unión de varios hashes?

Así es como se podría escribir una función que hace una especie de intersección de conjuntos devolviendo una lista de claves que ocurren en todos los hashes que se le pasan:

@common = inter(\%foo, \%bar, \%joe); 
sub inter { 
    my %seen; 
    for my $href (@_) { 
     while (my $k = each %$href) { 
      $seen{$k}++; 
     } 
    } 
return grep { $seen{$_} == @_ } keys %seen; 
}

entiendo que %seen es un hash de los cuales asigna cada clave a la cantidad de veces que se encontró en cualquiera de los valores proporcionados a la función.

Respuesta

16

grep tendrá una lista que se le pasa (en este caso, cada elemento visto en ninguna de las hashrefs); y devuelve una lista de solo aquellos elementos donde la expresión en el bloque es verdadera (localmente configurando la variable $_ para cada elemento en la lista). mirada

Vamos a la forma en que se evalúa la expresión:

  • @_ es una matriz de todos los parámetros pasados ​​a la subrutina - en nuestro caso, una lista de referencias de hash aprobadas en

  • En. $seen{$_} == @_ expresión esa lista se fuerza en un scalar context (debido a ==).

  • Cuando se utiliza en un contexto escalar, una lista se evalúa como el número de elementos de una lista -. En el ejemplo de la llamada anterior, a 3, desde hace 3 hashrefs fueron aprobadas en

Así, por cada clave en %seen (por ejemplo, cada clave vista en cualquiera de N hashrefs); la expresión $seen{$_} == @_ compara numéricamente el n. ° de veces que se vio el elemento en los hashes con el número total de hashes; por supuesto, solo va a ser igual si el elemento está en TODOS los hashes que se pasaron, y por lo tanto un miembro de la intersección que queremos.

Por lo tanto, para resumir el análisis, grep devolverá una lista de todas las claves que se producen en CADA hash (también aparecen N veces donde N es el número de hashes). P.ej. una intersección.

+0

Me gusta esta edición más reciente. Buena respuesta, DVK. – spazm

+0

Excelente. Me salvó el día. De hecho, escribí un fragmento de código para entender lo que estaba pasando y me estaba golpeando la cabeza a casi una hora, pero no pude entenderlo. – anukalp

2

El objetivo de la función es encontrar los elementos que aparecen en todos los hashes que se le pasan.

La última línea grep está la lista de regresar de keys %seen. Para determinar si aparece una clave dada en todos los valores hash que se pasaron a la función, podemos comparar el valor de esa clave en %seen con el número de argumentos en inter.

En el bloque grep, $_ se establece en cada elemento de la lista keys, y se prueba para alguna condición.

una matriz en contexto escalar evalúa a su longitud. @_ es la matriz de argumentos pasados ​​a la subrutina. Y el operador == pone sus operandos en contexto escalar, por lo que solo podemos comparar el valor de $seen{$_} con la longitud @_. Si son iguales, entonces esa clave apareció en todos los hashes.

3
grep block list 

Esto aplicará el bloqueo a cada elemento de la lista sucesivamente, el elemento tiene un alias de $ _. Si el bloque devuelve verdadero, el elemento se agrega a la matriz devuelta.

en este caso:

grep { $seen{$_} == @_ } keys %seen 

El bloque es $seen{$_} == @_, que compara el valor del hash visto contra @_. @_ se evalúa en contexto escalar y, por lo tanto, devuelve la cantidad de elementos en la matriz @_. @_ representa los argumentos para la función actual. En este caso (\%foo, \%bar, \%joe), que devuelve 3 en contexto escalar. Nuestra lista es keys %seen, que es una matriz que contiene todas las claves presentes en %seen.

declaraciones inglés equivalentes:

  • "Dame una lista de todas las claves de %seen donde el valor asociado con esa llave es igual al número de elementos pasados ​​a esta función"
  • "dame una lista de todas las claves de %seen donde el valor asociado con esa clave es 3"
  • "dame una lista de todas las llaves de %seen que tienen valor 3, es decir, todas las llaves de %seen que están presentes en cada uno de los 3 hashrefs pasados ​​a esta función"
Cuestiones relacionadas