in reply to Re^2: sorting by numbers then alphabetically
in thread sorting by numbers then alphabetically

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 } }

Replies are listed 'Best First'.
Re^4: sorting by numbers then alphabetically
by Anonymous Monk on Dec 23, 2010 at 18:21 UTC
    ok - that works too :)
      how would i do this by passing an array reference and not the array. can you call sort on an array ref?
        You need to send a list of things into the sort function. If you have a ref to an array, just de-reference that to get the the list of stuff.
        @$aref = sort @$aref;
        Update: The way that a Schwartzian transform works more efficiently is that it pre-computes this stuff like: my $a_region = lc ($a->region_name); so that it doesn't have be redone again and again for each pair of things to be compared.

        The Perl sort algorithm changes from release to release. Version 5.10 which I use now, uses merge sort instead of quick sort. In my benchmarking it is, in general, faster, much faster than previous versions. The net of this is that techniques like the Schwartzian transform don't bring as big a percentage decrease in sort time because there are fewer comparisons being done.

        As a beginner, I would recommend keeping things simple. Don't knock yourself out to gain a 10-15% reduction in something that is usually so fast anyway that it doesn't matter. That's why I offered my sort solution.

        Do not confuse brevity with execution efficiency and certainly not clarity! The "if" part of my code will run very quickly and could also be combined into a Schwartzian transform solution (the key part is the pre-computation of say lc($a).

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

        Enjoy, Have FUN! H.Merijn
Re^4: sorting by numbers then alphabetically
by TenThouPerlStudents (Initiate) on Dec 24, 2010 at 00:37 UTC

    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.

      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.

      HA!

        SO you think "HA!" is worth a post, eh? Well, whoever you are, I've taught THOUSANDS of Perl students, and not ONE of them has ever come back to me saying that ANY employer has ever disapproved of their code. And I teach OOP Perl, DBI, DB_File, and other way advanced Perl stuff like IO::Socket. Most of the people on this site would not PASS my intro Perl class. You heard me.

        And I can tell you that the so-called Perl "community" is largely responsible, alas, for the increasing popularity of Python. Perl is a WONDERFUL language but the Perl community has an adolescent mindset.

        And my credentials speak for themselves. I did kernel level stuff in C at the Stanford Research Institute in the 1980s. Perhaps you were in diapers then, yes??

        You got anything except "ha!"???