Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Sort array - subroutine help

Reply
Thread Tools

Sort array - subroutine help

 
 
Nath
Guest
Posts: n/a
 
      08-16-2004
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;


Thanks
Nathan


 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      08-16-2004
On Mon, 16 Aug 2004, Nath wrote:

> 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;
>


untested:

sub mySort {
return -1 if $a->[0] eq 'NEXUS' or $b->[0] eq 'User Defined';
return 1 if $b->[0] eq 'NEXUS' or $a->[0] eq 'User Defined';
$a->[0] cmp $b->[0];
}

@$output_aln_types = sort mySort @$output_aln_types;



Paul Lalli
 
Reply With Quote
 
 
 
 
Josef Moellers
Guest
Posts: n/a
 
      08-16-2004
Nath wrote:
> 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', '*.*'],
> ];


>
> @$output_aln_types = sort { $a->[0] cmp $b->[0] } @$output_aln_types;


How about:

@$output_aln_types = sort { $a->[0] eq 'NEXUS' ? -1 : $b->[0] eq 'NEXUS'
? 1 : $a->[0] eq 'User Defined' ? 1 : $b->[0] eq 'User Defined' ? -1
: $a->[0] cmp $b->[0] } @$output_aln_types;

--
Josef Möllers (Pinguinpfleger bei FSC)
If failure had no penalty success would not be a prize
-- T. Pratchett

 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      08-16-2004
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
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      08-16-2004
>>>>> "N" == Nath <DON'T_SEND_ME@TRIPE_TO_MY_IN.BOX> writes:

N> I have an array of arrays:
N> my $output_aln_types = [
N> ['Clustal', '.aln'],
N> ['NEXUS', ['.nex', '.nexus']],
N> ['Phylip', [ '.phy', '.phylip', '.phlp', '.phyl', '.phy', '.ph' ]],
N> ['FASTA', [ '.fas', '.fasta', '.fast', '.seq', '.fa', '.fsa',
N> '.nt', '.aa' ] ],
N> ['MEGA', [ '.meg', '.mega' ]],
N> ['User Defined', '*.*'],
N> ];

N> I want to sort it so that it is alphabetical, BUT with 'NEXUS' first, and
N> 'User Defined' last. the sort should return the following array of arrays:

N> @$output_aln_types = sort { $a->[0] cmp $b->[0] } @$output_aln_types;

<untested>

use Sort::Maker ;

my $sorter = make_sorter( style => 'GRT', string => q{
$_->[0] eq 'NEXUS' ? '' :
$_->[0] eq 'User Defined' ? "\xff" :
$_->[0] } ) ;

my @sorted = $sorter->(@unsorted) ;

note that '' (used as the key for NEXUS) will sort before all regular
strings). and 0xff (used as the key for 'User Defined') will sort after
all regular. otherwise the regular string key is used.

this will also be much faster (if the input array size is large enough)
than the common sort block.

and it is much clearer than the other solutions which have redundant
code and you have to know when to return 1 or -1. the tradeoff is a
module and knowing how to create key values that sort before/after all
normal keys.

uri


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
use one subroutine's variable value in another subroutine inside a module. king Perl Misc 5 04-29-2007 06:39 AM
using sort directly on subroutine returning list Kirk Is Perl Misc 5 11-26-2004 08:35 AM
Array sort function sorts on chars not numbers ... help ! how to sort numbers GIMME Javascript 5 07-26-2004 01:28 AM
How do I call sort with an anonymous subroutine stored in a hash ?? Casey Perl 3 01-30-2004 03:39 PM
Ado sort error-Ado Sort -Relate, Compute By, or Sort operations cannot be done on column(s) whose key length is unknown or exceeds 10 KB. Navin ASP General 1 09-09-2003 07:16 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57