#!/usr/bin/perl -w use strict; my @unordered = qw( 2HB 3HB C CA CB CG CD1 CD2 CE1 CZ CE2 HE2 HE1 HH HD1 HD2 N O OH ); # weighting hashes my %main = ( N => '1', CA => '2', C => '3', O => '4', S => '5', P => '6', H => '7', ); my %greek = ( B => '1', G => '2', D => '3', E => '4', Z => '5', H => '6', ); sub sortable { my $atom = shift; # get components $atom =~ /(\d)?(N|CA|C|O|S|P|H)(B|G|D|E|Z|H)?(\d)?/; my ($left,$main,$greek,$right) = ( $1, $2, $3, $4 ); # get weights or use default early sorting values $main = $main ? $main{ $main } : '0'; my $main_alone; # need to flag if main element is alone if ( $greek ) { $main_alone = '1'; $greek = $greek{ $greek }; } else { $main_alone = '0'; $greek = '0'; } $left ||= '0'; $right ||= '0'; # I assume that left numbers take precedence over right "$main_alone$main$greek$left$right"; } # use the string "cmp" operator - we are comparing strings, # not numbers. We could have populated # the weighting hashes with letters instead of numbers my @ordered = sort { sortable( $a ) cmp sortable( $b ) } @unordered; # if you have to get the value out of an object it would be: # @ordered = sort { sortable( $a->AtomName ) cmp sortable( $b->AtomName ) } @unordered; print join "\n", map { $_ ."\t". sortable( $_ ) } @ordered; #### N 01000 CA 02000 C 03000 O 04000 CB 13100 CG 13200 CD1 13301 CD2 13302 CE1 13401 CE2 13402 CZ 13500 OH 14600 2HB 17120 3HB 17130 HD1 17301 HD2 17302 HE1 17401 HE2 17402 HH 17600