Click here to get back home

sorting a hash / 2008-06-01

 HomeNewsGroups | Search | About
 comp.lang.perl.misc    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
sorting a hash / 2008-06-01 dn.perl@gmail.com 05-30-2008
Get Chitika Premium
Posted by Dave Saville on June 14, 2008, 11:43 am
Please log in for more thread options
On Sat, 14 Jun 2008 07:47:54 UTC, "Peter J. Holzer"

<snip>

> Dynamic scoping is used very little these days because it is confusing
> and error-prone: You need to know from where a function is called to
> know which variables it is seeing. But it does exist and for some
> specialized uses it may even be clearer.

Ah, so there is a subtle difference between "my $thing" and "our
$thing" when declared outside of any code blocks. ie at the "top"
level of a script. I had never seen a condition before where one could
tell the difference. "my $thing" at that level *appears* to behave in
a global fashion in that everything can "see" it.

Thanks, you learn something new everyday, The trick is not to forget
it :-)

--
Regards
Dave Saville

NB Remove nospam. for good email address

Posted by Uri Guttman on June 12, 2008, 12:37 pm
Please log in for more thread options

>> wrote:
>>
>> my $site;

>> foreach $site (keys %sites)

x> The way foreach works, the $site inside the loop is not the same
x> as the $site declared outside the loop.

i was smelling a scoping issue since the sort sub used external stuff
and also the loop variable. i didn't spot the extra my $site. but i was
right in general! :)

x> There are a variety ways around this, but none of them are entirely
x> satisfactory. One would be to make the sub an ordinary subroutine,
x> rather than one made specifically to be used by sort, then invoke
x> it explicitly rather than implicitly:

or he could use a different name for the for loop variable. since for
variables are localized, it would be seen in the sort sub as he wrote
it. it was the my $site outside that was being seen by the sort
sub. regardless, it isn't a good idea to use sort subs that refer to
external variables - too dangerous as we have seen here.

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

Posted by Dave Saville on June 12, 2008, 1:28 pm
Please log in for more thread options
Thank you both very much for the education. Much appreciated.

--
Regards
Dave Saville

NB Remove nospam. for good email address

Posted by Eric Pozharski on June 12, 2008, 3:44 pm
Please log in for more thread options

*SKIP*
> EP> print "$site $_ $urls[0] $urls[1]\n"
> EP> foreach(
> EP> sort { $urls[0] <=> $urls[0]; }
> EP> sort { $urls[1] <=> $urls[1]; }
> EP> keys %});

> are you (or the OP) trying to do a multilevel sort?

Me. That was my guess.

> it looks like yours will work but it is unusual to do two sort passes.

I have unusual habbit of chaining C<map>s and C<grep>s. That was plain
inertia.

> and it relies on the sort to be stable (meaning equal keys stay in the
> same ordering post sort). perl now uses a stable sort but earlier
> versions didn't. it is not something you should depend upon.

I rarely C<sort> (honestly, I don't at all). However I've definetely
seen notes on stability of C<sort>. I was ignorant. Mea culpa.

*CUT*

--
Torvalds' goal for Linux is very simple: World Domination

Posted by Jim Gibson on June 11, 2008, 5:39 pm
Please log in for more thread options

> On Fri, 30 May 2008 13:11:22 UTC, Gunnar Hjalmarsson
>
> > dn.perl@gmail.com wrote:
> > > I want to sort a hash. The hash contains a list of cities and their
> > > temperature
> >
> > Well, I'd rather say it contains three hash references.
> >
> > This is one sensible way to sort that data structure:
> >
> > foreach my $state ( sort keys %hash ) {
> > print "State: $state\n";
> > foreach my $city ( sort { $a cmp $b } keys %{ $hash } ) {
> > print "$city = $hash\n";
> > }
> > print "\n";
> > }
>
>
> Sorry to jump in with another question but I have a very similar
> problem. I am processing a consolidated apache2 logfile. I have
> multiple virtual hosts. All I care about are the site, the page
> served, a counter and the date.
>
> So my hash looks like $urls Beyond that I have a counter
> and date thus:
> $urls[0]++; # count
> $urls[1] = $date;
>
> This works fine and I can list by site the page, count and date.
>
> foreach $site ( keys %urls)
> {
> foreach my $url (keys %})
> {
> print "$site $url $urls[0] $urls[1]\n";
> }
> }
>
> Putting a sort into the url loop gives me the results sorted by page
> as expected. What I cannot figure out is how to do it by count and by
> date.
>
> I have tried various ideas I found by google but they all tend to be
> similar to this
>
> sub by_count
> {
> $urls[0] <=> $urls[0] or $a cmp $b;
> }
>
> But this throws lots of "Use of uninitialized value....." errors on
> that line and in doing so gets the wrong pages attributed to a site. I
> have tried with yet another hash on the end with count & date keys
> instead of the array, but it does not help.
>
> I would be grateful for any pointers.

Are you trying to sort all of your records at once, regardless of site?
You can't do that with a simple sort. If you just want to sort the data
by site, here is an example:


#!/usr/local/bin/perl
use strict;
use warnings;

my %urls = (
site1 => {
url1_1 => [ 3, '2008-01-01' ],
url1_2 => [ 2, '2008-02-02' ],
url1_3 => [ 5, '2008-02-03' ],
url1_4 => [ 4, '2008-03-05' ],
},
site2 => {
url2_1 => [ 7, '2008-09-11' ],
url2_2 => [ 4, '2008-03-10' ],
url2_3 => [ 1, '2008-02-24' ],
url2_4 => [ 8, '2008-03-31' ],
}
);

print "Sorted by site, url:\n";
for my $site ( sort keys %urls ) {
for my $url ( sort keys %} ) {
my( $count, $date ) = @};
print "$site, $url, $count, $date\n";
}
}

print "Sorted by site, count:\n";
for my $site ( sort keys %urls ) {
for my $url (
sort { $urls->[0] <=> $urls->[0] }
keys %} )
{
my( $count, $date ) = @};
print "$site, $url, $count, $date\n";
}
}

If you want something else, please post a complete program showing what
you are trying to do. Thanks.

--
Jim Gibson

Similar ThreadsPosted
Sorting a hash containing a hash of hashes December 14, 2005, 2:29 pm
Hash Sorting June 14, 2005, 2:49 pm
Sorting Hash by Value and Key May 17, 2007, 9:57 am
Sorting on sub-hash values June 23, 2005, 11:30 am
Sorting AofH over hash key(s)... October 30, 2007, 4:40 pm
Nested sorting of a hash December 6, 2007, 6:23 am
warnings on sorting hash of hashes January 5, 2005, 11:53 pm
sorting data - hash vs. list September 11, 2005, 4:41 pm
Sorting array of hash references October 26, 2006, 6:21 am
Sorting "string" numerical keys from a hash. September 5, 2004, 2:47 pm

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap