or=3D"black" face=3D"arial"><=
/span>
-----Original Message-----
From: Barry Brevik <BBrevik@StellarMicro.com>
Sent: Wed, Mar 31, 2010 8:36 pm
Subject: Help with sort
-family: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 1=
2px;">
> I'm having a problem=
sorting data items that are alpha-numeric strings. I know how to do it if =
the string is all alpha or all numeric, but the combo eludes me. Take=
as example the following code. It is my desire that the machine names be p=
rocessed in the order that they have been loaded into the hash. This is an =
example only- the machine names will not actually be loaded in order. Also,=
there will not always be "dashes" separating the alpha from the =
numbers: use strict; use warnings; my %mdata =
= =A0 ( 'CALIBRATION1', =A0 1, =
9;CALIBRATION02', 1, 'LABVIEW-1', =
1, 'LABVIEW-2', 1, =
'LABVIEW-4', 1, 'LABVIEW-11'=
, =A0 1, 'LABVIEW-12', =A0 1,=A0=
=A0 'LABVIEW-114', 1, 'YESTECH-L3=
-RW1',=A0 1, 'YESTECH-L03-RW2', 1, '=
;YESTECH-L4-RW125',1 ); foreach my $key (sort(keys(%m=
data))) { print "$key
> ";
> }
>=A0
> The output of this code is as follows, and you can see that the sort <=
br>
> order is not what I wanted:
>
> CALIBRATION02
> CALIBRATION1
> LABVIEW-1
> LABVIEW-11
> LABVIEW-114
> LABVIEW-12
> LABVIEW-2
> LABVIEW-4
> YESTECH-L03-RW2
> YESTECH-L3-RW1
> YESTECH-L4-RW125
>
> Any ideas on how to get this to come out in the "right" orde=
r?
>=A0
> Barry Brevik
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
here's a multi-key recursive approach that may fill the bill=
:
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
use warnings;
use strict;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
use List::Util qw(shuffle);
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
MAIN: {=A0 # begin main loop
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
# test words in desired sorted order
my @words =3D qw(
=A0 CALIBRATION1
=A0 CALIBRATION02
=A0 LABVIEW-1
=A0 LABVIEW-2
=A0 LABVIEW-4
=A0 LABVIEW-11
=A0 LABVIEW-12
=A0 LABVIEW-114
=A0 YESTECH-L3-RW1
=A0 YESTECH-L03-RW2
=A0 YESTECH-L4-RW125
=A0 );
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
my $ordered =3D join ' ', @words;=A0 # words in desired order
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
my @sorted =3D sort multi_key shuffle @words;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
print "$_ \n" for @sorted;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
die "FAILED: not desired order" unless $ordered eq join ' =
9;, @sorted;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
print "desired order";
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
}=A0 # end main loop
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
exit;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
sub multi_key {
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0 # assumes $a and $b are always defined.
=A0 return length($a) <=3D> length($b) unless length($a) and le=
ngth($b);
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0 # at this point, neither $a nor $b are empty string.
=A0 my ($a_alpha, $a_numeric, $a_dashed) =3D split_key($a);
=A0 my ($b_alpha, $b_numeric, $b_dashed) =3D split_key($b);
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0 return $a_alpha cmp $b_alpha
=A0 || $a_numeric <=3D> $b_numeric
=A0 || do { local ($a, $b) =3D ($a_dashed, $b_dashed);=A0=
multi_key(); }
;
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0 }
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
sub split_key {
=A0 $_[0] =3D~ m{ \A ([[:alpha:]]*) (\d*) (?<=3D .) (?: - (.+))? \=
z }xms
=A0 or die "malformed key: ``$_[0]''";<=
br>
=A0 return $1, $2 ? 0+$2 : 0, defined($3) ? $3 : '';
=A0 }
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
Output:
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
>perl
=
recursive_multikey_sort_1.pl
CALIBRATION1
CALIBRATION02
LABVIEW-1
LABVIEW-2
LABVIEW-4
LABVIEW-11
LABVIEW-12
LABVIEW-114
YESTECH-L3-RW1
YESTECH-L03-RW2
YESTECH-L4-RW125
desired order
y: Tahoma,Verdana,Arial,Sans-Serif; color: rgb(0, 0, 0); font-size: 12px;">=
=A0