in reply to sorting by numbers then alphabetically

Swarzian transform

my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] || $a->[2] cmp $b->[2] } map { my $s = $_->seq_region_name; [ $_, $s =~ m/^[0-9]+$/ ? $s : 999, $s ] } @unsorted;

Enjoy, Have FUN! H.Merijn

Replies are listed 'Best First'.
Re^2: sorting by numbers then alphabetically
by Anonymous Monk on Dec 23, 2010 at 17:39 UTC
    that worked a treat though i have no idea how it works! Is it case sensitive? I don't want it to be? If i could manipulate by object properties directly i would set the properties and test but i can't
      That uses a technique called a Schwartzian Transform, but you don't need to use it here. Aside from that, I'm not 100% sure that the comparison is going to work in all cases. It may very well. Below is another way.

      Basically compare using "cmp" if both things contain a non-digit, use "<=>" if both things are pure digits, if there is a mixture (one thing is pure digits, one thing is not) then the pure digit thing appears before the other in sort order. The sort subroutine needs to return, -1(a<b),0(a=b),1(a>b)and you can have any code to do that that you want.

      Perhaps you would want say some function that sorted the days of the week, in Europe weeks start on Monday, but in the US weeks start on Sunday. You could do that by making a subroutine that returns the appropriate -1,0,1 values. Cool.

      @sorted = sort by_num_then_letter @unsorted; sub by_num_then_letter { my $a_region = lc ($a->region_name); my $b_region = lc ($b->region_name); my $a_non_digit = ($a_region =~ /\D/); my $b_non_digit = ($b_region =~ /\D/); if ($a_non_digit and $b_non_digit) { $a_region cmp $b_region } elsif (!$a_non_digit and !$b_non_digit) { $a_region <=> $b_region } elsif ($a_non_digit) #digit only thing is always less than { 1; # b > a (reverse 1 and -1 if I got this wrong) } else { -1; # b<a } }
        ok - that works too :)

        I'm happy to see, Marshall, that this site has a few people who are out to HELP people with clear, unobfuscated code which doesn't require N maps.

        Map is a phenomenally powerful function but it is way too easy to get "map drunk". Other readers of Marshall's code would do well to emulate its simplicity and readability.

        We all have the common goal of wanting Perl to succeed but I can assure you that its formerly huge edge over Python is shrinking largely because some coders seem determined to violate the early Unix concepts of parsimony, smallness, and simplicity.