2009-10-13 13 views
19

¿Cómo puedo mantener el orden de la lista real después de contar su ocurrencia usando un hash en el siguiente programa? Por ejemplo, <DATA> son¿Cómo puedo mantener el orden de las claves que agrego a un hash Perl?

a 
b 
e 
a 
c 
d 
a 
c 
d 
b 
etc. 

Uso de hash, conté la ocurrencia de cada elemento.

y lo que quiero decir:

a 3 
b 2 
e 1 
c 2 
d 2 

pero el siguiente programa me muestra lo contrario.

my (%count, $line, @array_1, @array_2); 
while ($line = <DATA>) { 
    $count{$line}++ if ($line =~ /\S/); 
} 
@array_1 = keys(%count); 
@array_2 = values(%count); 
for(my $i=0; $i<$#array_1; $i++) 
{ 
    print "$array_1[$i]\t $array_2[$i]"; 
} 
+0

Puedes etiquetar tu código para leerlo fácilmente. – Space

+0

Entonces, usted ha hecho cinco preguntas, recibió muchas respuestas para todas ellas y ninguna de ellas ha sido lo suficientemente buena para ser aceptada, ¿o sí? –

+0

@Sinan: No ... no es que ...... no pude encontrar el lugar para reconocer todas las respuestas maravillosas ... solo me preguntaba si se hacía agregando un comentario o si había otro lugar ... .un novato para stackoverflow así como perl ... Lo siento, tal vez debería tomarme un tiempo para aprender a participar activamente en esta plataforma ... Casi todas las respuestas me dieron una nueva idea para aprender ... y sirvió para mis propósitos ... – Cthar

Respuesta

13

de datos en una tabla hash se almacena en orden de código hash las claves, que para la mayoría de los propósitos es como un orden aleatorio. También desea almacenar el orden de la primera aparición de cada tecla. He aquí una manera de abordar este problema:

my (%count, $line, @display_order); 
while ($line = <DATA>) { 
    chomp $line;   # strip the \n off the end of $line 
    if ($line =~ /\S/) { 
     if ($count{$line}++ == 0) { 
      # this is the first time we have seen the key "$line" 
      push @display_order, $line; 
     } 
    } 
} 

# now @display_order holds the keys of %count, in the order of first appearance 
foreach my $key (@display_order) 
{ 
    print "$key\t $count{$key}\n"; 
} 
+3

En mi humilde opinión, esta es una solución mejor que usar Tie :: IxHash, que creo que está más allá de las necesidades originales del OP. Es más adecuado usar el orden de visualización de las teclas, como en esta respuesta, o usar 'foreach my $ key (claves de clasificación% count) {...}' – Ether

30

hashes no están ordenados, pero como de costumbre, CPAN ofrece una solución: Tie::IxHash

use Tie::IxHash; 
my %count; 
tie %count, 'Tie::IxHash'; 

while ($line = <DATA>) { 
$count{$line}++ if ($line =~ /\S/); 
} 

while(my($key, $value)= each %count) { 
    print "$key\t $value"; 
} 
5

Simplemente:

my (%count, @order); 
while(<DATA>) { 
    chomp; 
    push @order, $_ unless $count{$_}++; 
} 
print "$_ $count{$_}\n" for @order; 
__DATA__ 
a 
b 
e 
a 
c 
d 
a 
c 
d 
b 
3

No estoy convencido de que esta sea siempre una técnica mejor, pero la he usado a veces. En lugar de tener el tipo de hash "visto", puede almacenar tanto el recuento como el orden notado.

Básicamente, en lugar de $count{$line} que tiene el número de veces visto, $count{$line}{count} es los tiempos vistos y $count{$line}{order} es el orden en el que se ve.

my %count; 
while (my $line = <DATA>) { 
    chomp $line; 
    if ($line =~ /\S/) { 
     $count{$line} ||= { order => scalar(keys(%count)) }; 
     $count{$line}{count}++; 
    } 
} 

for my $line (sort { $count{$a}{order} <=> $count{$b}{order} } keys %count) { 
    print "$line $count{$line}{count}\n"; 
} 
4

Otra opción es de David de oro (@xdg) Perl puro sencilla Hash::Ordered módulo. Obtienes orden pero es más lento ya que el hash se convierte en un objeto detrás de escena y usas métodos para acceder y modificar los elementos hash.

Probablemente haya puntos de referencia que puedan cuantificar cuánto más lento es el módulo que hashes regulares, pero es una forma genial de trabajar con estructuras de datos clave/valor en scripts pequeños y lo suficientemente rápido para mí en ese tipo de aplicaciones. La documentación menciona varios otros enfoques para ordenar un hash también.

Cuestiones relacionadas