2009-10-13 10 views
19

Jak mogę zachować kolejność rzeczywistej listy po zliczeniu jej występowania za pomocą skrótu w następującym programie? Na przykład, <DATA>Jak mogę zachować kolejność kluczy dodawanych do skrótu w pliku Perla?

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

za pomocą mieszania, to liczy się występowania każdego elementu.

i co chcę jest:

a 3 
b 2 
e 1 
c 2 
d 2 

ale Poniższy program pokazuje mi inaczej.

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

Czy możesz oznaczyć swój kod, aby go łatwo przeczytać. – Space

+0

Tak więc, zadałeś pięć pytań, otrzymałeś mnóstwo odpowiedzi na wszystkie z nich i żaden z nich nie był wystarczająco dobry, aby zostać zaakceptowanym, czy tak? –

+0

@Sinan: Nie ... to nie to ...... nie mogłem znaleźć miejsca, aby potwierdzić wszystkie wspaniałe odpowiedzi .... po prostu zastanawiasz się czy to się robi przez dodanie komentarza czy jest tam inne miejsce .... nowicjusz do stackoverflow, a także perl ... Przepraszam, może powinienem zająć trochę czasu, aby nauczyć się aktywnie uczestniczyć w tej platformie ... Niemal wszystkie odpowiedzi dały mi nowy pomysł na naukę ... i służyły moim celom ... – Cthar

Odpowiedz

13

Dane w tabeli mieszania jest przechowywane w kolejności kodu skrótu klawiszy, które dla większości celów jest jak losowej kolejności. Chcesz również zachować kolejność pierwszego pojawienia się każdego klawisza. Oto jeden ze sposobów podejścia do tego problemu:

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

IMHO to lepsze rozwiązanie niż użycie Tie :: IxHash, co moim zdaniem wykracza poza pierwotne potrzeby OP. Bardziej odpowiednie jest użycie kolejności wyświetlania klawiszy, jak w tej odpowiedzi, lub użycie 'foreach my $ key (sort keys% count) {...}' – Ether

30

Hashe nie są uporządkowane, ale jak zwykle, CPAN oferuje rozwiązanie: 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

prosto:

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

Nie jestem przekonany, że to zawsze jest lepsza technika, ale używałem jej czasami. Zamiast po prostu mieć "widoczny" typ skrótu, może on przechowywać zarówno liczbę, jak i kolejność zauważoną.

Zasadniczo, zamiast $count{$line} o podanej liczbie razy, $count{$line}{count} jest czasem widzianym, a $count{$line}{order} jest kolejnością, w jakiej był widziany.

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

Inną opcją jest złoty za Davida (@xdg) prosty czysty Perl Hash::Ordered. Zyskujesz porządek, ale jest wolniejszy, ponieważ hasz staje się obiektem za kulisami i używasz metod uzyskiwania dostępu i modyfikowania elementów haszujących.

Istnieją prawdopodobnie benchmarki, które pozwalają oszacować, o ile wolniejszy jest moduł niż zwykłe skróty, ale jest to fajny sposób na pracę z strukturami danych klucz/wartość w małych skryptach i wystarczająco szybki dla mnie w tego rodzaju aplikacji. Dokumentacja wspomina również o kilku innych podejściach do zamawiania skrótu.

Powiązane problemy