#!/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;