Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi folks,

I am currently working on a project to produce an analysis of the technologies being used on the web. For example, the number of sites using JavaScript, VBScript, CSS, Flash, Applets. I have developed the spider and collected lots of results. To display the results I have developed a website

http://www.webchalkboard.com/bot/index.shtml

I have just published this months results, and if you go to this page and select the month you want to view results for, you will notice that the results are split down into different domains.

Ok, my problem is how to sort these countries alphabetically. I know this sounds a very simple problem, and i've checked the Q&A section for details but found nothing. The domains are stored in a hash, with the key being 'COM' and the value being 'Commercial Sites' for example. So how can I put these countries in order, because when I loop through the hash, this is the order they come out in...?

I hope that makes sense and someone can point me in the right direction.

Many thanks, Tom

Replies are listed 'Best First'.
Re: Sorting My Hash
by vladb (Vicar) on May 22, 2002 at 14:27 UTC
    Assuming I understand the way you structured your hash correctly, let me suggest this solution:
    my %domain_stats = ( 'www.perlmonks.com' => { 'country' => 'USA', # ... other very much needed fields ... }, 'www.google.ca' => { 'country' => 'Canada', }, 'www.foobar.com' => { # does this one exist even? ;) 'country' => 'Nebukadnezaria', }, ); for (sort {$domain_stats{$a}{country} cmp $domain_stats{$b}{country}} +keys %domain_stats) { print "Domain: $_; Country: $domain_stats{$_}{country}\n"; }
    This prints out the following:
    Domain: www.google.ca; Country: Canada Domain: www.foobar.com; Country: Nebukadnezaria Domain: www.perlmonks.com; Country: USA


    _____________________
    $"=q;grep;;$,=q"grep";for(`find . -name ".saves*~"`){s;$/;;;/(.*-(\d+) +-.*)$/;$_=&#91"ps -e -o pid | "," $2 | "," -v "," "]`@$_`?{print" ++ $1"}:{print"- $1"}&&`rm $1`;print"\n";}
Re: Sorting My Hash
by Molt (Chaplain) on May 22, 2002 at 14:16 UTC

    Without seeing the code it's difficult to give you the definitive 'solve' for your particular question, but in general the way to get a hash sorted is to replace the for $key (keys %hash) with a for $key (sort keys %hash).

    If you want to sort on the value part of the key bear in mind that reverse'ing a hash will produce a hash where key/values have been switched, this is a nice and simple quick solution. For a nice and complex solution look into the Schwartzian Transform.

Re: Sorting My Hash
by broquaint (Abbot) on May 22, 2002 at 14:19 UTC
    Hashes are intrinsically unsorted so the way to iterate through a hash in a sorted order is either to sort the keys or the values like so
    my %hash = ( foo => 'some text', bar => 'more text', baz => 'less text', quux => 'dead text' ); print "%hash sorted by keys\n\n"; foreach my $k (sort keys %hash) { print "$k: $hash{$k}\n"; } print "\n%hash sorted by values\n\n"; foreach my $v (sort values %hash) { print "$v\n"; } __output__ %hash sorted by keys bar: more text baz: less text foo: some text quux: dead text %hash sorted by values dead text less text more text some text
    For more info about hashes in perl check out the perldata man page, for the functions used in the above code see sort(), keys() & values() and if you're dealing with nested hashes see perlref.
    HTH

    _________
    broquaint