Buscar..


Introducción

Para ordenar las listas de cosas, Perl tiene una sola función, como es lógico que se llame sort . Es lo suficientemente flexible como para ordenar todo tipo de elementos: números, cadenas en cualquier número de codificaciones, estructuras de datos anidadas u objetos. Sin embargo, debido a su flexibilidad, hay bastantes trucos e idiomas que aprender para su uso.

Sintaxis

  • ordenar la LISTA DE NOMBRES
  • ordenar la lista de bloqueo
  • Lista Ordenada

Ordenación léxica básica

@sorted = sort @list;

@sorted = sort { $a cmp $b } @list;

sub compare { $a cmp $b }
@sorted = sort compare @list;

Los tres ejemplos anteriores hacen exactamente lo mismo. Si no proporciona ninguna función o bloque de comparador, la sort asume que desea que la lista esté ordenada de forma léxica. Esta suele ser la forma que desea si solo necesita sus datos en un orden predecible y no le importa la corrección lingüística.

sort pasa pares de elementos en @list a la función de comparación, que le dice a sort qué elemento es más grande. El operador cmp hace esto para cadenas mientras que <=> hace lo mismo para los números. El comparador se llama con bastante frecuencia, en promedio n * log ( n ) veces, siendo n el número de elementos a clasificar, por lo que es importante que sea rápido. Esta es la razón por la que la sort usa variables globales predefinidas del paquete ( $a $b ) para pasar los elementos que se compararán con el bloque o función, en lugar de los parámetros de función adecuados.

Si use locale , cmp tiene en cuenta el orden de intercalación específico de la configuración regional, por ejemplo, clasificará Å como A en una configuración regional danesa, pero después de Z en una configuración inglesa o alemana. Sin embargo, no tiene en cuenta las reglas de clasificación de Unicode más complejas ni ofrece ningún control sobre el pedido; por ejemplo, las guías telefónicas a menudo se clasifican de forma diferente a los diccionarios. Para esos casos, se recomiendan los módulos Unicode::Collate y particularmente Unicode::Collate::Locale .

Orden numérico

@sorted = sort { $a <=> $b } @list;

La comparación de $a y $b con el operador <=> garantiza que se comparen numéricamente y no textualmente como por defecto.

Orden inverso

@sorted = sort { $b <=> $a } @list;
@sorted = reverse sort { $a <=> $b } @list;

Clasificación de elementos en orden descendente, simplemente se puede lograr mediante el canje $a y $b en el bloque comparador. Sin embargo, algunas personas prefieren la claridad de un reverse separado aunque sea un poco más lento.

La transformada de Schwartzian

Este es probablemente el ejemplo más famoso de una optimización de ordenación que utiliza las funciones de programación funcional de Perl, para usarse donde el orden de los elementos depende de una función costosa.

# What you would usually do
@sorted = sort { slow($a) <=> slow($b) } @list;

# What you do to make it faster
@sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, slow($_) ] }
@list;

El problema con el primer ejemplo es que el comparador se llama muy a menudo y sigue recalculando los valores usando una función lenta una y otra vez. Un ejemplo típico sería ordenar los nombres de los archivos por su tamaño de archivo:

use File::stat;
@sorted = sort { stat($a)->size <=> stat($b)->size } glob "*";

Esto funciona, pero en el mejor de los casos incurre en la sobrecarga de dos llamadas al sistema por comparación, en el peor, tiene que ir al disco dos veces para cada comparación y ese disco puede estar en un servidor de archivos sobrecargado en el otro lado del planeta.

Entra en el truco de Randall Schwartz.

La Transformación de Schwartz, básicamente, empuja @list través de tres funciones, de abajo hacia arriba. El primer map convierte cada entrada en una lista de dos elementos del elemento original y el resultado de la función lenta como una clave de ordenación, por lo que al final de esto llamamos slow() exactamente una vez para cada elemento. La siguiente sort puede simplemente acceder a la clave de clasificación mirando en la lista. Como no nos importan las claves de clasificación, sino que solo necesitamos los elementos originales en orden, el map final elimina las listas de dos elementos de la lista ya ordenada que recibe de @sort y devuelve una lista de solo sus primeros miembros .

Case Insensitive Sort

La técnica tradicional para hacer sort ignorar caso es pasar cadenas a lc o uc para la comparación:

@sorted = sort { lc($a) cmp lc($b) } @list;

Esto funciona en todas las versiones de Perl 5 y es completamente suficiente para el inglés; No importa si usas uc o lc . Sin embargo, presenta un problema para idiomas como el griego o el turco, donde no hay correspondencia 1: 1 entre las letras mayúsculas y minúsculas, por lo que obtiene diferentes resultados dependiendo de si usa uc o lc . Por lo tanto, Perl 5.16 y superior tienen una función de plegado de caja llamada fc que evita este problema, por lo que la clasificación multilingüe moderna debería usar esto:

@sorted = sort { fc($a) cmp fc($b) } @list;


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow