Nath <DON'T_SEND_ME@TRIPE_TO_MY_IN.BOX> wrote in comp.lang.perl.misc:
> I have an array of arrays:
>
> my $output_aln_types = [
> ['Clustal', '.aln'],
> ['NEXUS', ['.nex', '.nexus']],
> ['Phylip', [ '.phy', '.phylip', '.phlp', '.phyl', '.phy', '.ph' ]],
> ['FASTA', [ '.fas', '.fasta', '.fast', '.seq', '.fa', '.fsa',
> '.nt', '.aa' ] ],
> ['MEGA', [ '.meg', '.mega' ]],
> ['User Defined', '*.*'],
> ];
>
> I want to sort it so that it is alphabetical, BUT with 'NEXUS' first, and
> 'User Defined' last. the sort should return the following array of arrays:
>
> my $output_aln_types = [
> ['NEXUS', ['.nex', '.nexus']],
> ['Clustal', '.aln'],
> ['FASTA', [ '.fas', '.fasta', '.fast', '.seq', '.fa', '.fsa',
> '.nt', '.aa' ] ],
> ['MEGA', [ '.meg', '.mega' ]],
> ['Phylip', [ '.phy', '.phylip', '.phlp', '.phyl', '.phy', '.ph' ]],
> ['User Defined', '*.*'],
> ];
>
> i can use the following subroutine to sort alphabetically, but don't know
> how to place the 2 conditions of 'NEXUS' first, and 'User Defined' last:
>
> @$output_aln_types = sort { $a->[0] cmp $b->[0] } @$output_aln_types;
Lots of ways. You could sort using a specific comparison routine
that sorts "NEXUS" first and "User Defined" last:
@$output_aln_types = sort compare @$output_aln_types;
sub compare {
my ( $x, $y) = ( $a->[ 0], $b->[ 0]);
return -1 if $x eq 'NEXUS';
return 1 if $y eq 'NEXUS';
return 1 if $x eq 'User Defined';
return -1 if $y eq 'User Defined';
$x cmp $y;
}
Or you could exclude the special elements from the list and treat them
separately:
my ( $nexus) = grep $_->[ 0] eq 'NEXUS', @$output_aln_types;
my ( $user_defined) = grep $_->[ 0] eq 'User Defined', @$output_aln_types;
@$output_aln_types = sort { $a->[0] cmp $b->[0] }
grep { $_->[ 0] ne 'NEXUS' and $_->[ 0] ne 'User Defined' }
@$output_aln_types;
unshift @$output_aln_types, $nexus;
push @$output_aln_types, $user_defined;
....or sort the list no matter what, and move the special elements to
their places later:
@$output_aln_types = sort { $a->[0] cmp $b->[0] } @$output_aln_types;
my ( $i) = grep $output_aln_types->[ $_]->[ 0] eq 'NEXUS',
0 .. $#$output_aln_types;
unshift @$output_aln_types, splice @$output_aln_types, $i, 1;
( $i) = grep $output_aln_types->[ $_]->[ 0] eq 'User Defined',
0 .. $#$output_aln_types;
push @$output_aln_types, splice @$output_aln_types, $i, 1;
The last two solutions rely on the existence of "NEXUS" and "User Defined"
in the original list. If that can't be guaranteed, it should be checked.
The first solution doesn't care if one or both are missing.
Anno