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