• Publicidad

Ordenando un hash por sus valores y por sus llaves

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Ordenando un hash por sus valores y por sus llaves

Notapor MARKO » 2012-07-02 13:10 @590

Saludos, Perl en Español.

Necesito ordenar el siguiente hash de horas->precio:
sin orden.png
sin orden.png (7.59 KiB) Visto 884 veces
(el ingreso es 1->precio, 2->precio, 3->precio y así sucesivamente pero al imprimir el hash sale en el orden mostrado.

Curioseando en el foro me fui hacia un articulo que Uds. recomendaron y escribí esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. foreach my $hora( sort ordenar_por_valor keys %precio) {
  2.   my $valor = $precio{$hora};
  3.   print "$hora => $valor\n";
  4. }
  5.  
  6. sub ordenar_por_valor {
  7.   return $precio{$a} <=> $precio{$b};
  8. }
  9.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

el cual nos da el siguiente resultado:
orden parcial.png
orden parcial.png (10.06 KiB) Visto 884 veces


Como podrán ver, la hora (1,2,3,4,5,24) tienen el precio menor y las horas (19, 20, 21 y 22) tienen el precio mayor.

A mi solo me interesa el precio menor y el mayor pero con la primera hora con que apareció algo así:

%precio [
1 = > 140.65300329,
2 = > 140.65300329,
3 = > 140.65300329,
4 = > 140.65300329,
5 = > 140.65300329,
24 = > 140.65300329,
.
.
.
.
19 = > 167.96513356
20 = > 167.96513356
21 = > 167.96513356
22 = > 167.96513356
]

simplemente es coincidencia que el precio menor haya quedado en las primeras horas y el mayor en las últimas, podría haber sucedido en cualquier hora del día pero lo que me interesa es que se ordenen primeramente por el precio y luego por su llave.

¿Tengo el enfoque correcto o sería mejor meterlo en un arreglo y hacer el proceso "burbuja" para ordenar? ¿Ideas?

Gracias por adelantado.
MARKO
Perlero nuevo
Perlero nuevo
 
Mensajes: 86
Registrado: 2012-01-10 22:34 @982

Publicidad

Re: Ordenando un hash por sus valores y por sus llaves

Notapor explorer » 2012-07-02 14:06 @629

El almacenamiento de información dentro de un hash siempre es orden "aleatorio".

Para ordenador por los precios, y además, por las horas, solo hay que modificar un poco la condición de comparación (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub ordenar_por_valor {
  2.     return
  3.         $precio{$a} <=> $precio{$b}
  4.                      ||
  5.                 $a  <=> $b
  6.     ;
  7. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
De esa manera, estamos primero comparando -numéricamente y por orden ascendente- por el precio, y en el caso de igualdad de precio, el orden lo define la comparación -también numéricamente y por orden ascendente- de los valores de las claves (las horas).

Otra opción: como solo hay un precio por hora, podrías haber usado un array, y te ahorrabas algo de código.

Edito: hummm, quizás no te ahorras tanto código como yo creía.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ordenando un hash por sus valores y por sus llaves

Notapor MARKO » 2012-07-02 16:59 @749

Gracias por tu pronta respuesta.

Probé con el código que recomiendas, el orden cambió un poco pero no es el óptimo. Además aparecen muchas líneas de advertencia de error "odd number of elements in anonymous hash":
OTRO ORDEN.png
OTRO ORDEN.png (21.69 KiB) Visto 852 veces


¿Qué me recomiendas hacer si solo me interesa obtener el valor mínimo y la primera hora a la que este valor ocurrió y lo mismo para el valor máximo; el valor máximo y la primera hora a la que este valor ocurrió?

Las demás horas y precios pueden ser obviadas.

Otra opción: como solo hay un precio por hora, podrías haber usado un array, y te ahorrabas algo de código.

¿Método de ordenamiento burbuja o qué me recomiendas? De que no es menos código estoy seguro.

Gracias por adelantado.
MARKO
Perlero nuevo
Perlero nuevo
 
Mensajes: 86
Registrado: 2012-01-10 22:34 @982

Re: Ordenando un hash por sus valores y por sus llaves

Notapor explorer » 2012-07-03 01:30 @104

Por favor, no publiques volcados gráficos. Copia y pega siempre texto. Veo que es una consola de MSDOS, y sí que puedes copiar ese texto, con el ratón.

MARKO escribiste:Probé con el código que recomiendas, el orden cambió un poco pero no es el óptimo. Además aparecen muchas líneas de advertencia de error "odd number of elements in anonymous hash":
OTRO ORDEN.png
Sin ver un código de ejemplo, es difícil decir qué pasa.
El mensaje de error dice que el hash tiene un número impar de elementos, así que se te está colando algún elemento, o pones un elemento de más, o algo así.

MARKO escribiste:¿Qué me recomiendas hacer si solo me interesa obtener el valor mínimo y la primera hora a la que este valor ocurrió y lo mismo para el valor máximo; el valor máximo y la primera hora a la que este valor ocurrió?
Es muy sencillo: ordenas el hash como te indiqué, y luego solo hay que leer el primer par y el último par.

MARKO escribiste:¿Método de ordenamiento burbuja o qué me recomiendas?
Nada, no hay que hacer nada de eso. Con ordenarlo una vez, vale.

Edito: Este es un ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3.  
  4. my %precios = (
  5.     1   => 140.65,
  6.     2   => 140.65,
  7.     3   => 140.65,
  8.     4   => 140.65,
  9.     5   => 140.65,
  10.     6   => 150.27,
  11.     7   => 154.12,
  12.     8   => 163.73,
  13.     9   => 162.60,
  14.     10  => 154.12,
  15.     11  => 154.12,
  16.     12  => 154.12,
  17.     13  => 154.12,
  18.     14  => 163.73,
  19.     15  => 163.73,
  20.     16  => 163.73,
  21.     17  => 163.73,
  22.     18  => 163.73,
  23.     19  => 167.97,
  24.     20  => 167.97,
  25.     21  => 167.97,
  26.     22  => 167.97,
  27.     23  => 150.27,
  28.     24  => 140.65,
  29. );
  30.  
  31. my @horas_ordenadas = sort { $precios{$a} <=> $precios{$b} || $a <=> $b } keys %precios;
  32.  
  33. for (@horas_ordenadas) {
  34.     say "$_ => $precios{$_}";
  35. }
  36.  
  37. my $hora_precio_mas_bajo = 0;
  38. my $hora_precio_mas_alto = $#horas_ordenadas;
  39.  
  40. while ($hora_precio_mas_alto > 0) {                     # encontrar la primera hora con precio más alto
  41.     last if $precios{$horas_ordenadas[$hora_precio_mas_alto-1]} != $precios{$horas_ordenadas[-1]};
  42.  
  43.     $hora_precio_mas_alto--;
  44. }
  45.  
  46. say "Precio más bajo: $precios{$horas_ordenadas[$hora_precio_mas_bajo]}";
  47. say "Primera hora con ese precio: $horas_ordenadas[$hora_precio_mas_bajo]";
  48. say "Precio más alto: $precios{$horas_ordenadas[$hora_precio_mas_alto]}";
  49. say "Primera hora con ese precio: $horas_ordenadas[$hora_precio_mas_alto]";
  50.  
  51. __END__
  52. 1 => 140.65
  53. 2 => 140.65
  54. 3 => 140.65
  55. 4 => 140.65
  56. 5 => 140.65
  57. 24 => 140.65
  58. 6 => 150.27
  59. 23 => 150.27
  60. 7 => 154.12
  61. 10 => 154.12
  62. 11 => 154.12
  63. 12 => 154.12
  64. 13 => 154.12
  65. 9 => 162.6
  66. 8 => 163.73
  67. 14 => 163.73
  68. 15 => 163.73
  69. 16 => 163.73
  70. 17 => 163.73
  71. 18 => 163.73
  72. 19 => 167.97
  73. 20 => 167.97
  74. 21 => 167.97
  75. 22 => 167.97
  76. Precio más bajo: 140.65
  77. Primera hora con ese precio: 1
  78. Precio más alto: 167.97
  79. Primera hora con ese precio: 19
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ordenando un hash por sus valores y por sus llaves

Notapor MARKO » 2012-07-05 13:57 @623

Perfecto, explorer, me ayudaste muchísimo.

Muchísimas gracias.
MARKO
Perlero nuevo
Perlero nuevo
 
Mensajes: 86
Registrado: 2012-01-10 22:34 @982


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 22 invitados