Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

A generic sorting problem

by frankus (Priest)
on Jul 19, 2002 at 09:24 UTC ( [id://183171]=perlquestion: print w/replies, xml ) Need Help??

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

Ok, I've got a piece of code where an array is sorted.
Sometimes the array is all numbers, other times all characters.
The artless way (to me) seemed to be to check the first element and sort depending on that.

What I settled for was a catch-all:

for my $line (sort {unpack('C4',$a) <=> unpack('C4',$b) } keys %$value +) { tinker_with($line); }

Some of the time the job of the Pack is redundant, other times, not so.
Is there a better way of doing this?

--

Brother Frankus.

¤

Replies are listed 'Best First'.
Re: A generic sorting problem
by demerphq (Chancellor) on Jul 19, 2002 at 10:11 UTC
Re: A generic sorting problem
by Abigail-II (Bishop) on Jul 19, 2002 at 10:10 UTC
    Your "catchall" doesn't seem to catch all:
    use strict; use warnings 'all'; my @array1 = (1, 2, 3, 4, 5, 15, 14, 13, 12, 11); my @array2 = sort {unpack('C4',$a) <=> unpack('C4',$b)} @array1; print "@array2\n"; __END__ 1 11 14 15 13 12 2 3 4 5
    which is just a normal alphabetical sort.

    Abigail

Re: A generic sorting problem
by bronto (Priest) on Jul 19, 2002 at 10:50 UTC

    A solution could be to take advantage of the possibility to feed sort a reference to a sorting subroutine. That way you could check if the first element is a number (for example with $array[0] =~ /^\d+$/) and select the right subroutine:

    my @array = (12,23,34,56,876,324,13) ; # Use the array below to test for alphas #my @array = qw(mamma ninnonnina domani festa din don dan) ; my $sortsub ; my $sortnum = sub { $a <=> $b } ; my $sortalpha = sub { $a cmp $b } ; $sortsub = $array[0] =~ /^\d+$/ ? $sortnum : $sortalpha ; my @sorted = sort $sortsub @array ; print map "$_\n",@sorted ;

    Note however that this approach is far from optimal in this case. In fact when the array contains alphas you replace the fast native sorting with a slower $sortalpha. This approach is better suited for selecting a sort sub in more complicated sorting.

    Ciao!
    --bronto

    # Another Perl edition of a song:
    # The End, by The Beatles
    END {
      $you->take($love) eq $you->made($love) ;
    }

Re: A generic sorting problem
by choocroot (Friar) on Jul 19, 2002 at 10:17 UTC
    I think you should use the cmp and <=> operators in the sort subroutine, like this :
    @a = qw( words only contains ); @b = qw( 8 3 7 1 ); print join( " ", sort { $a <=> $b || $a cmp $b } @a ), "\n"; # contains only words print join( " ", sort { $a <=> $b || $a cmp $b } @b ), "\n"; # 1 3 7 8
    This way you can even sort numbers AND letters :
    @a = qw( 2 two 1 one ); print join( " ", sort { $a cmp $b || $a <=> $b } @a ), "\n"; # 1 2 one two
      Your first two examples would raise warnings galore when handling non numeric values, and the second example is simply an alphabetic sort, equivelent to sort @a

      use warnings; use strict; my @a = qw( 2 two 1 11 12 one 3abcd 6foo ); print join( " ", sort { $a <=> $b || $a cmp $b } @a ), "\n"; __END__ Argument "two" isn't numeric in numeric comparison (<=>) at c:\temp\so +rt.pl line 4. Argument "one" isn't numeric in numeric comparison (<=>) at c:\temp\so +rt.pl line 4. Argument "3abcd" isn't numeric in numeric comparison (<=>) at c:\temp\ +sort.pl line 4. Argument "6foo" isn't numeric in numeric comparison (<=>) at c:\temp\s +ort.pl line 4. one two 1 2 3abcd 6foo 11 12
      and
      #... print join( " ", sort { $a cmp $b || $a <=> $b } @a ), "\n"; __END__ 1 11 12 2 3abcd 6foo one two

      Yves / DeMerphq
      ---
      Writing a good benchmark isnt as easy as it might look.

        Oops :( you are absolutely right !

        But is there a way to do this without getting the warnings messages ? by localizing $^W I guess ? or simply by not using this kind of construction :)))

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://183171]
Approved by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-03-19 09:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found