そのような形式でソートするための論理(追加モジュールではない)を探しています。次のような文字列のリストがあります。
asdadasBBBsfasdasdas-0112
asdanfnfnfnfnf222ads-1210
たとえば、次の理由から、数字だけで並べ替えることはできません。812> 113(812 = 2012年8月、113 = 2013年1月、したがって正しくありません)
良い戦略はありますか?
ありがとう、
シュワルツ変換はどうですか:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);
my @list = (
'asdadasBBBsfasdasdas-0112',
'asdanfnfnfnfnf222ads-1210',
'asdanfnfnfnfnf222ads-1211',
'asdanfnfnfnfnf222ads-1010',
'asdanfnfnfnfnf222ads-1011',
);
my @sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] or $a->[2] <=> $b->[2] }
map { /-(\d\d)(\d\d)$/; [$_, $2, $1] } @list;
dump @sorted;
出力:
(
"asdanfnfnfnfnf222ads-1010",
"asdanfnfnfnfnf222ads-1210",
"asdanfnfnfnfnf222ads-1011",
"asdanfnfnfnfnf222ads-1211",
"asdadasBBBsfasdasdas-0112",
)
シュワルツ変換はここでは大きな無駄になります。名前を思い出せないこの似たような構成の方がはるかに優れています。
my @sorted =
map substr($_, 4),
sort
map substr($_, -2) . substr($_, -4, 2) . $_,
@unsorted;
の代わりに一致演算子を使用するsubstr
:
my @sorted =
map substr($_, 4),
sort
map { /(..)(..)\z/s; $2.$1.$_ }
@unsorted;
最初に年を調べ、次に日付を調べるソート関数を使用します。
sub mmyy_sorter {
my $a_yy = substr($a, -2);
my $b_yy = substr($b, -2);
my $a_mm = substr($a, -4, 2);
my $b_mm = substr($b, -4, 2);
return ($a_yy cmp $b_yy) || ($a_mm cmp $b_mm);
}
my @sorted = sort mmyy_sorter @myarray;
注意:これは、配列内のアイテムごとに1回だけでなく、比較ごとに月と年のサブフィールドを再計算する必要があるため、技術的には効率的ではありません。
すべての値は実際には数値を表すため、Perlの自動型変換を利用して<=>
、の代わりに演算子を使用することも可能です。cmp
サンプルデータを提供してくれた@M42に感謝します。
use strict;
use warnings;
use feature 'say';
my @list = (
'asdadasBBBsfasdasdas-0112',
'asdanfnfnfnfnf222ads-1210',
'asdanfnfnfnfnf222ads-1211',
'asdanfnfnfnfnf222ads-1010',
'asdanfnfnfnfnf222ads-1011',
);
my @sorted = sort {
my ($aa, $bb) = map { /(..)(..)\z/ and $2.$1 } $a, $b;
$aa <=> $bb;
} @list;
say for @sorted;
出力
asdanfnfnfnfnf222ads-1010
asdanfnfnfnfnf222ads-1210
asdanfnfnfnfnf222ads-1011
asdanfnfnfnfnf222ads-1211
asdadasBBBsfasdasdas-0112
数ヶ月にリメイクするのはどうですか?例えば:
812 = 12 * 12 + 8
113 = 13 * 12 + 1
あなたは年を月に変えることができ、それは良いでしょう。番号の選択には、正規表現を使用できます。