Práctica: Ordenar por Calificaciones

Se tiene un fichero de entrada con calificaciones de alumnos como el que sigue:
Ferrer Pérez, Eduardo & 9'6\\
García  García, Laura & 7'5 \\
García Medina, Anai & 6'5\\
García Rodríguez, Pedro & 7'2\\
González del Castillo, Jorge & 5'0\\
Hernández Pérez, Daniel & 5'0\\
Marrero Díaz, Jose Antonio & 8'0\\
Marrero Piñero, Sergio & 7'2\\
Padrón Padrón, Adolfo & 5'0\\
Pedrín Ruiz, Ana & 9'6\\
Pedrínez Pérez, Ignacio & 7'5\\
Piñero Piñero, Antonio & 5'3\\
Pérez García, Adolfo & 9'5\\
Pérez González, Germán & 5'0\\
Pérez Pedrínez, Maria & 5'0\\
Ramos Ramos, Ignacio & 5'0\\
Rodríguez González, Andrés & 10'0\\
Rodríguez Rodríguez, Jorge & 9'2\\
Lea el fichero (para saber como leer un fichero cuyo nombre ha sido pasado en la línea de argumentos léa la sección 2.1 ) de manera que los elementos queden almacenados en un hash indexado en los nombres de los alumnos. Ordene el hash en orden decreciente de calificaciones. Observe que las números se han escrito según la convención española de usar apóstrofes en vez del punto decimal. Una posibilidad es que utilice el operador de sustitución para convertirlo a punto. Por ejemplo, $a =~ s/'/./ sustituirá el primer apóstrofe en $a por un punto. También le puede ayudar el uso de paréntesis con memoria en expresiones regulares. Veamos un ejemplo:
lhp@nereida:~/Lperl/src$ perl -wde 0 notas.txt
main::(-e:1):   0
  DB<1> @a = <>             # Leemos el fchero 'notas.txt' en @a
  DB<2> p @a[0..3]          # 4 primeras líneas
Ferrer Pérez, Eduardo & 9'6\\
García  García, Laura & 7'5 \\
García Medina, Anai & 6'5\\
García Rodríguez, Pedro & 7'2\\

  DB<3> %h = map { /(.*)\s+\&\s+(\d+'\d*).*/ } @a 
  DB<4> p $h{'Ferrer Pérez, Eduardo'}
9'6
  DB<5> p $h{'García Medina, Anai'}
6'5
  DB<7> $h{$_} =~ s/'/./ for (keys %h)
  DB<8> p $h{'García Medina, Anai'}
6.5
  DB<9> @b = sort { $h{$b} <=> $h{$a} } keys %h
  DB<10> print "$_ => $h{$_}\n" for (@b[0..5])
Rodríguez González, Andrés => 10.0
Pedrín Ruiz, Ana => 9.6
Ferrer Pérez, Eduardo => 9.6
Pérez García, Adolfo => 9.5
Rodríguez Rodríguez, Jorge => 9.2
Marrero Díaz, Jose Antonio => 8.0
  DB<11> $max = max(map { length } @b)    # Salida formateada
  DB<12> printf("%-${max}s\t=>\t%4s\n",$_,$h{$_}) for @b[0..3]
Rodríguez González, Andrés      =>      10.0
Pedrín Ruiz, Ana                =>       9.6
Ferrer Pérez, Eduardo           =>       9.6
Pérez García, Adolfo            =>       9.5

El uso de la expresión regular en la línea 3 en un contexto de lista hace que map construya una lista de pares (nombre, nota) que es ''enrollada'' en el hash %h. Los pares (nombre, nota) son retornados por la expresión regular al ser el resultado del matching con el primer y segundo paréntesis.

Puede que le convenga leer las secciones 3.1, 3.2 y 3.4 y en particular el uso de paréntesis y el operador de sustitución en las expresiones regulares.

Para la ordenación repase la sección 1.13.2 y en particular el ejemplo en el que los usuarios del sistema se ordenan según su uid.

Casiano Rodríguez León
Licencia de Creative Commons
Principios de Programación Imperativa, Funcional y Orientada a Objetos Una Introducción en Perl/Una Introducción a Perl
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=43.
2012-06-19