tags:

views:

237

answers:

5

how to maintain the order of actual list after counting its occurence using hash... in the following program... eg.. <DATA> are

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

Using hash... i counted the occurence 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]";
}
+9  A: 

Data in a hash table is stored in order of the keys' hash code, which for most purposes is like a random order. You also want to store the order of the first appearance of each key. Here's one way to approach this problem:

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";
}
mobrule
IMHO this is a better solution than using Tie::IxHash, which I think is beyond the OP's original needs. It is more suitable to use the display order of the keys, as in this answer, or to use `foreach my $key (sort keys %count) { ... }`
Ether
+11  A: 

Hashes are not ordered, but as usual, CPAN offers a solution: 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"; 
}
mirod
+4  A: 

Simply:

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
Hynek -Pichi- Vychodil
+2  A: 

From perlfaq4's answer to "How can I make my hash remember the order I put elements into it?"


How can I make my hash remember the order I put elements into it?

Use the Tie::IxHash from CPAN.

use Tie::IxHash;

tie my %myhash, 'Tie::IxHash';

for (my $i=0; $i<20; $i++) {
 $myhash{$i} = 2*$i;
 }

my @keys = keys %myhash;
# @keys = (0,1,2,3,...)
brian d foy
A: 

Declare your variables in the smallest possible scope. If you want to sort the keys of the hash for display purposes, feel free to do so. Avoid parallel arrays. When you have a $key, the corresponding value in the hash is $count{$key}.

#!/usr/bin/perl

use strict;
use warnings;

my %count;

while (<DATA>) {
    chomp;
    $count{$_}++ if /\S/;
}

my @sorted_keys = sort keys %count;
for my $key ( @sorted_keys ) {
    print "$key\t$count{$key}\n"
}
__DATA__
a
b
e
a
c
d
a
c
d
b

Output:

a       3
b       2
c       2
d       2
e       1
Sinan Ünür