sortで使用できるPerl比較関数が必要です。
各キーは、区切り文字(ドット、コロン、スペース、スラッシュ)で区切られた任意の数のサブキーを持つテキスト文字列です。一部のサブキーは数値であり、数値で並べ替える必要があります。キーの形式とサブキーの数は異なります。したがって、比較では、一方のキーがもう一方のキーよりも長い場合を処理する必要があり、サブキーが1つのキーでは数値であるが、別のキーでは数値でない場合を処理する必要があります(この場合、テキストによる比較がそのサブキーに適しています)。
これは機能しますが、もっと良い解決策があるに違いありません。
use warnings;
use strict;
use Scalar::Util qw[looks_like_number];
sub hier_cmp {
my $aa = $a;
my $bb = $b;
# convert all delims (. : / space) to the same delim
$aa =~ tr/.:\/ /::::/;
$bb =~ tr/.:\/ /::::/;
my @lista = split(":", $aa);
my @listb = split(":", $bb);
my $result;
for my $ix (0 .. min($#lista, $#listb)) {
if (exists($lista[$ix]) && exists($listb[$ix])) {
if ( looks_like_number($lista[$ix]) && looks_like_number($listb[$ix])) {
# compare numerically
$result = ($lista[$ix] <=> $listb[$ix]);
} else {
# compare as strings
$result = ($lista[$ix] cmp $listb[$ix]);
}
if ($result == 0) {
next;
}
return $result;
} elsif (exists($lista[$ix])) {
return 1;
} else {
return -1;
}
}
}
私の目的では、読みやすさは速度よりも重要です。これは内部ツール専用であり、リストに数百を超える要素が含まれることはめったにありません。ただし、何かを学ぶ機会はあります。
ご覧のとおり、私はPerlウィザードではありません。私のコードの些細な改善でさえいただければ幸いです。
ありがとう!