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

Hi Confreres,

i want to sort by hash keys.
How can I define exceptions?
e.g "normal"
my %hash = (auto=>1, bike=>1, foot=>1, motorbike=>1, boot=>1); for (sort {$a cmp $b } keys %hash){ print; }
result : auto, bike, boot, foot, motorbike

but how if it should be

      foot,      auto, bike, boot, motorbike
    <-first-> <-         sorted             ->
thanks in advance!
Murcia

Replies are listed 'Best First'.
Re: sort hash exceptions
by edan (Curate) on Jan 26, 2004 at 14:01 UTC

    Here's a slightly more generic version of Abigail's answer.

    my %except = ( foot => -1, # sorts first hand => 1, # sorts last ); sub except_sort { return exists $except{$a} ? $except{$a} : exists $except{$b} ? -$except{$b} : $a cmp $b; } my @list = qw/leg hand eye foot jaw finger/; print join(" ", sort except_sort @list), $/;
    --
    3dan

      The exists() aren't really necessary.
      sub except_sort { $except{$a} || -$except{$b} || ($a cmp $b) }

      _____________________________________________________
      Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
      s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

        That gives "Use of uninitialized value in negation (-)". (Yes, I know, the example you responded to was missing use warnings;), so you need -($except{$b}||0) instead.
Re: sort hash exceptions
by Abigail-II (Bishop) on Jan 26, 2004 at 13:55 UTC
    sort {$a eq "foot" ? -1 : $b eq "foot" ? 1 : $a cmp $b} keys %hash;
    Next time, please pick a more suitable title. Your question has nothing to do with hashes, just with sorting. The fact you happen to sort hash keys doesn't make the answer any different.

    Abigail

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: sort exceptions
by ysth (Canon) on Jan 26, 2004 at 23:08 UTC
    Here's a slightly more generic version of 3dan's answer. I prefer to think of them not as exceptions but as a primary sort key, derived through a hash lookup with a default of 0, with the straight cmp of the strings being the secondary sort key.
    use strict; use warnings; my %rank = ( tonsil => -2, # sorts very first foot => -1, # sorts before most hand => 1, # sorts after most chin => 1, # sorts after most pinky => 2, # sorts very last ); sub rank_sort { ($rank{$a}||0) <=> ($rank{$b}||0) || $a cmp $b } my @list = qw/leg hand chin eye pinky foot jaw tonsil finger/; print join(" ", sort rank_sort @list), $/;
    Note that if two different elements have the same rank, they will be determinately sorted, rather than depending on perl's sort stability (or lack thereof).