sort on multiple hash values

Discussion in 'Perl Misc' started by Zhiliang Hu, Oct 8, 2008.

  1. Zhiliang Hu

    Zhiliang Hu Guest

    I have a hash with multiple values, like in:

    Marty => 32877::2
    Bart => 14857::2
    Torq => 65221::1
    etc

    and I wish to sort on. say, first field of the hash value:

    foreach $key (sort mysort keys %hasha ) { ... }

    sub mysort {
    map { $_->[0] }
    sort { $a->[0] cmp $b->[0] }
    map { [ $_, split(/::/,[0] ] }
    }

    but confused as how to 'map' the elements... need help -- Thanks in
    advance!
     
    Zhiliang Hu, Oct 8, 2008
    #1
    1. Advertising

  2. Zhiliang Hu <> wrote:
    >I have a hash with multiple values, like in:
    >
    > Marty => 32877::2
    > Bart => 14857::2
    > Torq => 65221::1
    > etc
    >
    >and I wish to sort on. say, first field of the hash value:


    You don't because hashes by definition do not have a sequence and
    therefore cannot be sorted.

    What _do_ you want to sort? An array of the keys of the hash? An arrray
    of the values of the hash? Something totally different?

    See also the FAQ: "How do I sort a hash[...]?"

    jue
     
    Jürgen Exner, Oct 8, 2008
    #2
    1. Advertising

  3. Zhiliang Hu wrote:
    > I have a hash with multiple values, like in:
    >
    > Marty => 32877::2
    > Bart => 14857::2
    > Torq => 65221::1
    > etc
    >
    > and I wish to sort on. say, first field of the hash value:


    Have you thought about using a Hash of Arrays instead?

    my %hasha = (
    Marty => [ 32877, 2 ],
    Bart => [ 14857, 2 ],
    Torq => [ 65221, 1 ],
    );


    > foreach $key (sort mysort keys %hasha ) { ... }


    Why are you are supplying sort with a subroutine that has sort in it?
    Did you want to sort on the keys as well as the values?

    foreach my $key ( mysort keys %hasha ) { ... }


    > sub mysort {
    > map { $_->[0] }
    > sort { $a->[0] cmp $b->[0] }
    > map { [ $_, split(/::/,[0] ] }


    You are supplying split() with an anonymous array which translates to a
    number that has no ':' characters in it. The mysort subroutine is
    passed a list of keys from the %hasha hash in the @_ array but you are
    not accessing that list, but even if you were, to get the value from
    that key you need to get it from the hash as $hasha{$_}. You are
    comparing what would be the keys of the hash but you said you wanted to
    compare the values.


    > }
    >
    > but confused as how to 'map' the elements... need help -- Thanks in
    > advance!


    sub mysort {
    map $_->[ 0 ],
    sort { $a->[ 1 ] <=> $b->[ 1 ] }
    map [ $_, ( split /::/, $hasha{ $_ } )[ 0 ] ],
    @_
    }



    John
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall
     
    John W. Krahn, Oct 8, 2008
    #3
  4. Zhiliang Hu

    Zhiliang Hu Guest

    Sorry I must be in day-dreaming for these errors.
    Any way I changed my approach to have solved the problem. John's
    suggestion to use a hash of arrays is a good idea for the problem
    though (another evidence to see multiple ways to accomplish
    something!)

    Thanks for all the replies.

    Zhiliang
     
    Zhiliang Hu, Oct 10, 2008
    #4
  5. On 2008-10-08 18:04, Jürgen Exner <> wrote:
    > Zhiliang Hu <> wrote:
    >>I have a hash with multiple values, like in:
    >>
    >> Marty => 32877::2
    >> Bart => 14857::2
    >> Torq => 65221::1
    >> etc
    >>
    >>and I wish to sort on. say, first field of the hash value:

    >
    > You don't because hashes by definition do not have a sequence and
    > therefore cannot be sorted.


    Jürgen, can you please try to be little less literal? I see no
    indication that the OP wanted to create a hash with an intrinsic sort
    order.


    > What _do_ you want to sort? An array of the keys of the hash? An arrray
    > of the values of the hash?


    One of those two, almost certainly. It doesn't really matter, since the
    technique is the same, you just write

    sort { cmp_func($hash{$a}, $hash{$b}) } keys %hash
    in one case and
    sort { cmp_func($a, $b) } values %hash
    in the other (the OP already stated that the sort order depends only on
    the value, not the key).


    > Something totally different?


    Unlikely.


    > See also the FAQ: "How do I sort a hash[...]?"


    I don't see you berating Brian that he can't sort a hash ...

    hp
     
    Peter J. Holzer, Oct 11, 2008
    #5
  6. "Peter J. Holzer" <> wrote:
    >On 2008-10-08 18:04, Jürgen Exner <> wrote:
    >> Zhiliang Hu <> wrote:
    >>>I have a hash with multiple values, like in:
    >>>
    >>> Marty => 32877::2
    >>> Bart => 14857::2
    >>> Torq => 65221::1
    >>> etc
    >>>
    >>>and I wish to sort on. say, first field of the hash value:

    >>
    >> You don't because hashes by definition do not have a sequence and
    >> therefore cannot be sorted.

    >
    >Jürgen, can you please try to be little less literal? I see no
    >indication that the OP wanted to create a hash with an intrinsic sort
    >order.


    I guess that's my pet peeve. If people would stop talking about sorting
    a hash and instead spend just a minute thinking about what they _REALLY_
    want to do, then the solution would be obvious, please see below.

    [...]

    > sort { cmp_func($hash{$a}, $hash{$b}) } keys %hash


    This is I want to sort the keys of the hash by their associated values,
    using some criteria.

    >in one case and
    > sort { cmp_func($a, $b) } values %hash


    And this is I want to sort the values of the hash by their own values,
    using some criteria.

    Both follow the standard pattern "I want to sort X by criteria Y". The
    solution will jump right at you once you recognize that sort() takes two
    parameters: the compare function and the list(!) of data to be sorted.
    So first get that list (no, it is not the hash!), and then based on the
    elements in that list define your compare function.

    Once you forget the idea about sorting a hash and realize that actually
    you are sorting a list and that you have to create that list first, then
    the problem looses the 'rocket science complexity' and becomes trivial.

    Unfortunately most people keep insisting on thinking in terms of sorting
    a hash.... :-((

    jue
     
    Jürgen Exner, Oct 11, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Navin
    Replies:
    1
    Views:
    705
    Ken Schaefer
    Sep 9, 2003
  2. rp
    Replies:
    1
    Views:
    539
    red floyd
    Nov 10, 2011
  3. Replies:
    3
    Views:
    211
    William James
    Nov 5, 2005
  4. Tore Aursand
    Replies:
    3
    Views:
    557
    Anno Siegel
    Sep 16, 2003
  5. Patrick
    Replies:
    5
    Views:
    593
    Brian McCauley
    May 3, 2006
Loading...

Share This Page