my $extract = sub { my $x = lc($_[0]); if ($x =~ s/^(\d+)\s*//) { $x = $1 * { mbps => 10**6, kbps => 10**3, bps => 10**0, }->{$x}; } else { $x = { 't1 line' => 100000 }->{$x}; } die "Bad input $_[0]" unless $x; return $x; }; my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map [ $_, $extract->( $_ ) ], @array; #### { $a->[1] <=> $b->[1] or $b->[2] <=> $a->[2] or $a->[3] cmp $b->[3] # ...compare as many sort keys as you please } #### { mbps => 10**6, kbps => 10**3, bps => 10**0, }, { 't1 line' => 100000 } #### my %lookup = ( mbps => 10**6, kbps => 10**3, bps => 10**0, 't1 line' => 100000 ); my $extract = sub { my $x = lc($_[0]); if ($x =~ s/^(\d+)\s*//) { $x = $1 * $lookup{ $x }; } else { $x = $lookup{ $x }; } die "Bad input $_[0]" unless $x; return $x; }; # etc.