カスタム コンパレータを指定することで、これを並べ替えることができます。並べ替えキーとして 2 レベルの値が必要なようです。そのため、カスタム コンパレーターは行のキーを取得し、それを比較します。
# You want karyotypical sorting on the first element,
# so set up this hash with an appropriate normalized value
# per available input:
my %karyotypical_sort = (
1 => 1,
...
X => 100,
);
sub row_to_sortable {
my $row = shift;
$row =~ /chr(.+):(\d+)-/; # assuming match here! Be careful
return [$karyotypical_sort{$1}, $2];
}
sub sortable_compare {
my ($one, $two) = @_;
return $one->[0] <=> $two->[0] || $one->[1] <=> $two->[1];
# If first comparison returns 0 then try the second
}
@lines = ...
print join "\n", sort {
sortable_compare(row_to_sortable($a), row_to_sortable($b))
} @lines;
計算は少し面倒なので (文字列の操作は無料ではありません)、おそらく大量のデータ (ゲノム!) を扱っているため、 Schwartzian Transformを実行するとパフォーマンスが向上することに気付くでしょう。これは、行のソート キーを事前に計算し、それを使用してソートし、最後に追加データを削除することによって実行されます。
@st_lines = map { [ row_to_sortable($_), $_ ] } @lines;
@sorted_st_lines = sort { sortable_compare($a->[0], $b->[0]) } @st_lines;
@sorted_lines = map { $_->[1] } @sorted_st_lines;
または組み合わせ:
print join "\n",
map { $_->[1] }
sort { sortable_compare($a->[0], $b->[0]) }
map { [ row_to_sortable($_), $_ ] } @lines;