On Fri, May 29, 2009 at 11:51, John W. Krahn <[email protected]> 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: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/