Se ha determinado que no usar map es nocivo para la salud

Ernesto Hernandez-Novich emhn at telcel.net.ve
Wed Apr 25 09:11:28 CDT 2001


Preámbulo:

- Esto es un hash explícito porque tiene nombre (%h).

  %h = ( clave0 => valor0, clave1 => valor1, ... , claveN => valorN );

  print $h{clave0} devuelve valor0

- Esto es un hash implícito, sin nombre del cual se tiene una
  _referencia_.

  $rh = { clave0 => valor0, clave1 => valor1, ..., claveN 0> valorN );

  print $rh->{clave0} devuelve valor0

  Nótese que $rh no es el hash sino un "apuntador" al hash, por lo
  tanto debo usar "->" para hacer la indirección.
  
La función map es una de las más poderosas de Perl. Representa un ciclo
implícito que opera sobre una lista, y que permite iterar sobre los
elementos de está aplicando una función; para los que hemos experimentado
con lenguajes funcionales es de lo más natural y poderosísimo porque
permite operar distributivamente sobre las estructuras de datos.

En general, si uno tiene una lista @l y quiere aplicar la funcion f() a
todos sus elementos tiene dos opciones:

a. Si se es un programador "standard" con mentalidad procedural, se apela
   a un algoritmo de la forma.

   foreach $e (@l) {
     push(@r,f($e));
   }
   @l = @r;

   En otras palabras, proceso iterativamente cada elemento, para lo cual
   necesito un ciclo explícito, una variable intermedia para moverme, un
   arreglo intermedio para los resultados, y una copia de arreglo al
   final. Patético.

b. Si se es un programador que ha sido introducido al "maravilloso mundo
   del map", se apela a

   @l = map { f($_) } @l;

   Si, así de simple.

Ahora, algunos ejemplos clásicos de uso de map que no solamente ahorran
espacio, sino también _mucho_ tiempo.

0. Eliminar los duplicados de una lista:

   @a = ( 'uno', 'dos', 'dos', 'tres', 'uno', 'cuatro', 'dos' );
   @a = keys %{ { map { $_ => 1 } @a } };

   Tomo la lista y construyo un hash implícito cuya clave son los
   elementos de la lista. Luego obtengo las claves de este hash, que
   obviamente son los elementos únicos de la lista original.

1. Obtener la unión de dos listas, i.e. los elementos que están en @a
   agregando los elementos que están en @b, sin duplicados:

   @a = ( 'uno', 'dos', 'dos', 'tres', 'uno', 'cuatro', 'dos' );
   @b = ( 'dos', 'tres', 'cuatro', 'ocho', 'nueve' );
   @i = keys %{ { map { $_ => 1 } (@a, at b) } };

   Debería ser obvio en base al ejemplo 0.

2. Determinar si un elemento está en una lista:

   $buscar = 'cuatro';
   @a = ( 'dos', 'tres', 'ocho', 'cuatro', 'once', 'dos' );
   if ( { map { $_ => 1 } @a }->{$buscar} ) {
     print "Si";
   } else {
     print "No";
   }

   Tomo la lista y construyo un hash implícito cuya clave son los
   elementos de la lista. Luego dereferencio el hash para ver si la
   clave del elemento a buscar existe.

3. Obtener la diferencia de dos listas @a y @b, i.e. @a - @b, los elementos
   de @a que _no_ están en @b (diferencia de conjuntos :-).

   @a = ( 'uno', 'dos', 'tres', 'cuatro', 'cinco' );
   @b = ( 'dos', 'cuatro', 'seis', 'ocho' );
   @d = map { { map { $_ => 1 } @b }->{$_} ? () : $_ } @a;

   (De adentro hacia afuera). Tomo la lista @b y construyo un hash
   implícito cuya clave son los elementos de la lista. Luego tomo la lista
   @a y verifico si en el hash implícito de @b existe un elemento cuya
   clave sea el elemento de @a, si es así devuelvo una lista vacía, en
   caso contrario devuelvo el elemento de @a.

Escriban los mismos algoritmos proceduralmente y luego comparen las
velocidades... ya verán por qué map es su amigo.
-- 
Ernesto Hernández-Novich - Running Linux 2.4.2 i686 - Unix: Live free or die!
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/E d+(++) s+: a C+++$ UBLAVHIOSC*++++$ P++++$ L+++$ E- W+ N++ o K++ w--- O-
M- V PS+ PE Y+ PGP>++ t+ 5 X+ R* tv+ b++ DI+++$ D++ G++ e++ h r++ y+
-----END GEEK CODE BLOCK-----

------------------------------------------------------------------------
Enviar e-mail a <majordomo at pm.org> colocando en el cuerpo:
"UNSUBSCRIBE caracas-pm-list" para desuscribirse.
"INFO caracas-pm-list" para conocer las reglas de etiqueta.
------------------------------------------------------------------------



More information about the caracas-pm mailing list