How can I maintain the order of keys I add to a Perl hash?

Viewed 28700

How can I maintain the order of actual list after counting its occurrence using a hash in the following program? For example, <DATA> are

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

Using hash, i counted the occurrence of each element.

and what i want is:

a  3
b  2
e  1
c  2
d  2

but the following program shows me otherwise.

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]";
}
7 Answers

Hashes are just arrays until they're assigned in Perl, so if you cast it as an array, you can iterate over it in its original order:

my @array = ( z => 6,
              a => 8,
              b => 4 );

for (my $i=0; $ar[$i]; ++$i) {
    next if $i % 2;
    my $key = $ar[$i];
    my $val = $ar[$i+1];

    say "$key: $val"; # in original order
}

You lose the benefits of hash indexing if you do that obviously. But since a hash is just an array, you can create one just by assigning the array to a hash:

my %hash = @array;
say $hash{z};

This is maybe just a variation on the "use an array as an index" solution, but I think it's neater because instead of typing out your index manually (or in some other way), you're creating it directly from the source array.

Related