On Fri, May 29, 2009 at 11:51, John W. Krahn <jwkr...@shaw.ca> wrote:
> Bryan Harris wrote:
>>
>> Let's say I have a bunch of lines of data in an array, @a:
>>
>>  car    72
>>  car    55
>>  truck    31
>>  bike    2
>>  car    12
>>  truck    16
>>  van    97
>>  car    64
>>
>> ... and I want to sort them so that the trucks are first, then the vans,
>> the bikes are third, cars are next, and everything else sorted
>> alphabetically at the end.
>>
>> I started down this route:
>>
>> @a = sort {
>>                   if ($a =~ /^truck/ && $b =~ /^truck/) { 0 }
>>                   elsif ($a =~ /^truck/ && $b =~ /^van/) { -1 }
>>                   ... } @a;
>>
>> ... but that quickly breaks down.  Then I thought, what about this?:
>>
>> @a = ( grep { /^truck/ } @a, grep { /^van/ } @a, grep { /^bike/ } @a, grep
>> { /^cars/ } @a, sort grep { !/^(truck|van|bike|cars)/ } @a);
>>
>> ... which seems to work, but looks clunky, feels like it'd be slow, and
>> doesn't scale well if my list of 5 things were to become 75.
>>
>> How is this kind of thing usually done?
>
>
> my %order = (
>    truck => 0,
>    van => 1,
>    bike => 2,
>    car => 3,
>    '' => 4
>    );
>
> my $regex = qr/^(truck|van|bike|car)/;
>
> my @sorted = sort { $order{ ( $a =~ $regex )[ 0 ] } <=> $order{ ( $b =~
> $regex )[ 0 ] } || $a cmp $b } @a;
snip


This is begging for a Schwartzian Transform[1]:

#!/usr/bin/perl

use strict;
use warnings;

my %order = (
        truck => 1,
        van   => 2,
        bike  => 3,
        car   => 4,
);

my @data;

while (<DATA>) {
        chomp;
        push @data, [split];
}

#sort by vehicle type first and number second if they are the same type
my @sorted =
        map  { $_->[1] }
        sort { $a->[0] <=> $b->[0] or $a->[1][1] <=> $b->[1][1] }
        map  { [ ($order{$_->[0]} || 100), $_ ] }
        @data;

print "unsorted:\n", format_data(@data), "\nsorted:\n", format_data(@sorted);

sub format_data {
        my $string;
        for my $rec (@_) {
                $string .= sprintf "%6s %2d\n", @$rec;
        }
        return $string;
}

__DATA__
car    72
car    55
truck  31
bike    2
car    12
other  15
other   6
truck  16
van    97
car    64


1. http://en.wikipedia.org/wiki/Schwartzian_Transform

-- 
Chas. Owens
wonkden.net
The most important skill a programmer can have is the ability to read.

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to