sorting hash by values 
Author Message
 sorting hash by values

I have a hash with a bunch of words as keys, and the number of times
they occured in the file as values.

I want to sort the values and print them out, with their corresponding
keys, in numerical order.

I have no problem doing this with keys, but haven't the slightest idea
how to do it with values.  Yes, I have looked at the perl faq, but
that was no help.

Any help appreciated...
thanks!



Wed, 24 Jan 2001 03:00:00 GMT  
 sorting hash by values

Quote:

> I have a hash with a bunch of words as keys, and the number of times
> they occured in the file as values.
> I want to sort the values and print them out, with their corresponding
> keys, in numerical order.
> I have no problem doing this with keys, but haven't the slightest idea
> how to do it with values.  Yes, I have looked at the perl faq, but
> that was no help.

foreach(sort {$hash{$a} <=> $hash{$b}} keys %hash) {
        print "$_ = $hash{$_}\n";

Quote:
}

This prints the keys and the value with the smallest value
first.

I think this information is found in the 'perlfunc' manpage...

Hope it helps...

/Magnus Jonsson

--


 \ (  |
  \_) `-- I only code for fun...



Wed, 24 Jan 2001 03:00:00 GMT  
 sorting hash by values

Quote:

>Yes, I have looked at the perl faq, but that was no help.

In Perlfaq 4, there is a section titled ``How do I sort a hash
(optionally by value instead of key)?''  If that was no help, I don't
think anyone here is going to be able to help you either.


Wed, 24 Jan 2001 03:00:00 GMT  
 sorting hash by values

Quote:

> Yes, I have looked at the perl faq, but
> that was no help.

weird, I did a grep "sort by val" and found a hit right away.

Your answer is in both perlfunc and perlfaq4

(Here's the answer from perlfunc)
"              To sort an array by value, you'll need to use a
               sort() function.  Here's a descending numeric sort
               of a hash by its values:

                   foreach $key (sort { $hash{$b} <=> $hash{$a} } keys %hash) {
                       printf "%4d %s\n", $hash{$key}, $key;
                   }
"

--
Jim Woodgate
Tivoli Systems



Wed, 24 Jan 2001 03:00:00 GMT  
 sorting hash by values

Quote:

> I have a hash with a bunch of words as keys, and the number of times
> they occured in the file as values.

> I want to sort the values and print them out, with their corresponding
> keys, in numerical order.

> [ ... ]

Try this ...

 %hash = ( 'dick'  => 5,
           'jane'  => 7,
           'sally' => 2,
           'spot'  => 1,
           'tim'   => 0,
           'puff'  => 3 );

 foreach $key ( sort { $hash{$a} <=> $hash{$b} } keys %hash ) {
    print "$key\t$hash{$key}\n";
 }

--

 perl -e '$n=170;for($d=2;($d*$d)<=$n;$d+=(1+($d%2))){for($t=0;($n%$d)==0;




Thu, 25 Jan 2001 03:00:00 GMT  
 sorting hash by values
Try this:

#!/usr/bin/perl

sub mysort {
    my ($gtl);
    if ( $hash{$a} == $hash{b})
        $gtl = $a cmp $b;
    } else {
        $gtl = $hash{$a} <=> $hash{$b};
    }
    return $gtl;

Quote:
}



    print "$_ : $hash($_)\n";

Quote:
}

> I have a hash with a bunch of words as keys, and the number of times
> they occured in the file as values.

> I want to sort the values and print them out, with their corresponding
> keys, in numerical order.

> I have no problem doing this with keys, but haven't the slightest idea
> how to do it with values.  Yes, I have looked at the perl faq, but
> that was no help.

> Any help appreciated...
> thanks!

--
   ****************************************
   *    Tony Labbiento                    *
   *    Infinity Online, Inc.             *
   ****************************************


Thu, 25 Jan 2001 03:00:00 GMT  
 sorting hash by values
Sorry, caught my own mistake. You need an open brace { where indicated
below. This is right after the conditional.

Quote:

> Try this:

> #!/usr/bin/perl

> sub mysort {
>     my ($gtl);
>     if ( $hash{$a} == $hash{b})

------------------------------------^ {

Quote:
>         $gtl = $a cmp $b;
>     } else {
>         $gtl = $hash{$a} <=> $hash{$b};
>     }
>     return $gtl;
> }



>     print "$_ : $hash($_)\n";
> }


> > I have a hash with a bunch of words as keys, and the number of times
> > they occured in the file as values.

> > I want to sort the values and print them out, with their corresponding
> > keys, in numerical order.

> > I have no problem doing this with keys, but haven't the slightest idea
> > how to do it with values.  Yes, I have looked at the perl faq, but
> > that was no help.

> > Any help appreciated...
> > thanks!

> --
>    ****************************************
>    *    Tony Labbiento                    *
>    *    Infinity Online, Inc.             *
>    ****************************************

--
   ****************************************
   *    Tony Labbiento                    *
   *    Infinity Online, Inc.             *
   ****************************************


Thu, 25 Jan 2001 03:00:00 GMT  
 sorting hash by values

Quote:

> sub mysort {
>     my ($gtl);
>     if ( $hash{$a} == $hash{b})
>         $gtl = $a cmp $b;
>     } else {
>         $gtl = $hash{$a} <=> $hash{$b};
>     }
>     return $gtl;
> }

There's a big efficiency problem in that code:
you compare $hash{$a} to $hash{$b} twice
(except in cases where they happen to be equal).  
If you compare them using <=> first, then you don't
have to compare them again.

First, rewrite so that the branches are swapped:

    if ( $hash{$a} != $hash{b} ) {
        $gtl = $hash{$a} <=> $hash{$b};
    } else {
        $gtl = $a cmp $b;
    }

Note that != and <=> evaluate identically in a boolean
context.  So use <=> for the boolean test:

    if ( $hash{$a} <=> $hash{b} ) {
        $gtl = $hash{$a} <=> $hash{$b};
    } else {
        $gtl = $a cmp $b;
    }

Now cache the value of that comparison:

    $gtl = $hash{$a} <=> $hash{$b};
    if ( $gtl ) {
    } else {
        $gtl = $a cmp $b;
    }

Which of course is the same as:

    $gtl = $hash{$a} <=> $hash{$b};
    if ( ! $gtl ) {
        $gtl = $a cmp $b;
    }

A nice shorthand for this situation, which happens
to crop up a lot, is:

    $gtl = $hash{$a} <=> $hash{$b};
    $gtl ||= $a cmp $b;

Of course, if that's all you're doing, you may as well say:

    $gtl = $hash{$a} <=> $hash{$b}
        || $a cmp $b;

So mysort actually looks like this:

    sub mysort {
        my $gtl;
        $gtl = $hash{$a} <=> $hash{$b} || $a cmp $b;
        return $gtl;
    }

Which is obviously nothing more than

    sub mysort {
        $hash{$a} <=> $hash{$b} || $a cmp $b;
    }

Which means you can skip the subroutine altogether:

  for (
    sort { $hash{$a} <=> $hash{$b} || $a cmp $b } keys %hash
  ) {
    ....
  }

I'd like to commend Tony for bringing up the good point
that the hash can be sorted by keys when the values are
equal.

--
John Porter



Fri, 26 Jan 2001 03:00:00 GMT  
 sorting hash by values
If you only have a small handful of entries in your hash then the
solutions other give can work fine, but they are very inefficient.

Often you must create a data structure (like this hash) with a mind for
your special needs.  I often create a hash where the value part is a
reference to a list and sometimes have the key value ALSO be a member of
that value list.  In effect I would have:

%hash = ( fred => ['fred', 1, "a"],
          sue => ['sue', 8, "m" ]
        );

Then I can sort fairly quickly as:

   foreach $entry (sort { $a->[1] cmp $b->[1] } values %hash)
      {
      print "$entry->[0] : $entry->[1]\n";
      }

For many of my uses of Perl I need to have a hash of references to lists
anyway so having the hash's key be another entry in the list is a minor
price to pay.  In effect you have a bunch of records that you want to keep
in a list to sort, etc. but you also need a hash to permit fast lookups --
so have both.



Sat, 27 Jan 2001 03:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. Sorting a hash by value and sub sorting the keys

2. Sorting a hash according to associated values in another hash

3. sorting hash of hash by values

4. Sorting a hash of hashes by values

5. sort a hash of hashes by value

6. Sorting hash of hashes by value

7. hash of values and array of hashes of values and array of hashes

8. hash value equal other hash value

9. Sorting a hash by its values

10. Sorting an array of hash references by the values of a particular key

11. sort hash by value: problem

12. NEWBIE: Sorting a hash by value

 

 
Powered by phpBB® Forum Software