Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: how do I sort on two fields in a hash table?

by lhoward (Vicar)
on Mar 15, 2001 at 22:50 UTC ( [id://64748]=note: print w/replies, xml ) Need Help??


in reply to how do I sort on two fields in a hash table?

foreach $junk (sort {$b->{'count'} cmp $a->{'count'} or $b->{'type'} cmp $a->{'type'}} @data) { print "$junk->{'count'} --> $junk->{'type'} --> $junk->{'a_point +'} -> $junk->{'z_point'} --> $junk->{'error'}\n"; }
If @data is large you may want to use a Schwartzian Transform (or other method of improving sort performance).

BTW, @data would more properly be called a "list of hashes".

Replies are listed 'Best First'.
Re: Re: how do I sort on two fields in a hash table?
by dvergin (Monsignor) on Mar 15, 2001 at 22:58 UTC
    What lhoward said, but if the values in $junk{count} are numerical values (as seems likely), the first half of the sort should use the spaceship comparison operator: {$b->{count} <=> $a->{count} Otherwise 12 will sort before 2.

    Note that quotes inside the curly braces are not needed.

    And discussions of the Merlynian Schwartzian Transform can be found here, here, and here. (Heady stuff but great when you need it!)

Re: Re: how do I sort on two fields in a hash table?
by knobunc (Pilgrim) on Mar 16, 2001 at 00:14 UTC
    I believe your or binds too loosely so you get:
    ( sort {$b->{'count'} cmp $a->{'count'} ) or $b->{'type'} cmp $a->{'type'}} @data
    (Note the parentheses above indicating the binding).

    What you want is:

    sort {$b->{'count'} <=> $a->{'count'} || $b->{'type'} cmp $a->{'type'}} @data
    Which binds more tightly. I also flipped the comparison operator for count since as dvergin pointed out above you probably want a numeric comparison for count.

    -ben

      I don't think so... my test program:
      #!/usr/bin/perl -w use strict; my @a; push @a,{x=>1,y=>1}; push @a,{x=>2,y=>1}; push @a,{x=>1,y=>2}; push @a,{x=>2,y=>3}; push @a,{x=>2,y=>2}; foreach(sort {$a->{x} <=> $b->{x} or $a->{y} <=> $b->{y}} @a){ print " $_->{x} $_->{y}\n"; }
      prints the correct results:
      $ ./sort.pl 1 1 1 2 2 1 2 2 2 3
      Thanks for your response. I thought that || was the same as or. How are they different? Txs

        They do the same thing, it's all about operator precedence. || has higher precedence than or, and other things in between. The perlop manpage has about everything you need to know. To steal an example from perlop, the following:
            unlink "alpha", "beta", "gamma" or gripe(), next LINE;
        works like:
            unlink("alpha", "beta", "gamma") or (gripe(), next LINE);
        but it would break using ||, because it would work like:
            unlink("alpha", "beta", ("gamma" || gripe()), next LINE;

Re: Re: how do I sort on two fields in a hash table?
by vonman (Acolyte) on Mar 16, 2001 at 00:51 UTC
    Just wanted to thank you. This is working great.
Re: Re: how do I sort on two fields in a hash table?
by vonman (Acolyte) on Mar 15, 2001 at 22:51 UTC
    Thanks for the info. This is the first program I have written using hashes. Thanks again for your help.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://64748]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (7)
As of 2024-04-23 17:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found