我需要幫助在perl中排序。我有這種格式的日期數組。 DD-MMM-YY。例19-FEB-12。在Perl中排序日期
我已經花了相當多的時間,但無法得到它的工作。我對perl也很陌生。任何數量的幫助表示讚賞。謝謝!!
我需要幫助在perl中排序。我有這種格式的日期數組。 DD-MMM-YY。例19-FEB-12。在Perl中排序日期
我已經花了相當多的時間,但無法得到它的工作。我對perl也很陌生。任何數量的幫助表示讚賞。謝謝!!
完全從頭開始:
打印輸出:
Unsorted:
14-OCT-06
15-OCT-06
13-OCT-06
19-FEB-12
29-DEC-02
15-JAN-02
Sorted (Least recent to most recent):
15-JAN-02
29-DEC-02
13-OCT-06
14-OCT-06
15-OCT-06
19-FEB-12
代碼:
#!C:\Perl64
#Input Strings
@inputs = ('14-OCT-06','15-OCT-06','13-OCT-06', '19-FEB-12', '29-DEC-02', '15-JAN-02');
print "Unsorted:\n";
foreach(@inputs){
print $_."\n";
}
# Hash for Month : Number
%months = ('JAN' => '01',
'FEB' => '02',
'MAR' => '03',
'APR' => '04',
'MAY' => '05',
'JUN' => '06',
'JUL' => '07',
'AUG' => '08',
'SEP' => '09',
'OCT' => '10',
'NOV' => '11',
'DEC' => '12');
# Hash for Number : Month
%revmonths = ('01'=>'JAN',
'02' => 'FEB',
'03' => 'MAR',
'04' => 'APR',
'05' => 'MAY',
'06' => 'JUN',
'07' => 'JUL',
'08' => 'AUG',
'09' => 'SEP',
'10' => 'OCT',
'11' => 'NOV',
'12' => 'DEC');
# Rearrange the order to 'Year-Month-Day'
@dates =();
foreach(@inputs){
my @split = split('-',$_);
my @rearranged = reverse(@split);
@rearranged[1] = $months{$rearranged[1]};
push(@dates, \@rearranged);
}
# Sort based on these three fields
@sorted = sort { $a->[2] <=> $b->[2] } @dates;
@sorted = sort { $a->[1] <=> $b->[1] } @sorted;
@sorted = sort { $a->[0] <=> $b->[0] } @sorted;
# Replace Month Number with Month name
$size = @sorted;
for $counter (0..$size-1){
my $ref = $sorted[$counter];
my @array = @$ref;
my $num = $array[1];
$array[1] = $revmonths{$array[1]};
my @array = reverse(@array);
$sorted[$counter] = \@array;
}
print "\nSorted (Least recent to most recent):\n";
foreach(@sorted){
my @temp = @$_;
my $day = $temp[0];
my $month = $temp[1];
my $year = $temp[2];
print $day."-".$month."-".$year;
print "\n";
}
我很驚訝這被標記爲接受的答案。 Borodin使用Time :: Piece(這是一個核心Perl模塊)的答案比較好。 –
一個簡單的方法是將日期轉換爲可按字典順序排序的YYYYMMDD
格式。
請注意,MM
應該是以兩位數字表示的月份。
您可以使用核心模塊Time::Piece
將DD-MMM-YY(或任何輸入格式)轉換爲ISO 8601格式。這允許簡單的分類。這個例子構建了一個包含ISO值作爲排序關鍵字的原始數據數組;對它進行分類;並以排序的順序返回數據:
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
my $t;
my @data;
while (<DATA>) {
chomp;
$t = Time::Piece->strptime($_, "%d %b %y");
push @data, [ $t->datetime, $_ ]; #...ISO 8601 format...
}
my @sorteddata = sort { $a->[0] cmp $b->[0] } @data;
for my $value (@sorteddata) {
print $value->[1], "\n";
}
__DATA__
19 Feb 12
17 Aug 11
31 Mar 10
01 Aug 11
08 Apr 11
29 Feb 11
這可以使用Time::Piece
核心模塊的strptime
方法日期解碼並根據所得到的劃時代秒排序它們來完成。
這個程序演示了這個想法。
use strict;
use warnings;
use Time::Piece;
my @dates = <DATA>;
chomp @dates;
my @sorted = sort {
Time::Piece->strptime($a, '%d-%b-%y') <=> Time::Piece->strptime($b, '%d-%b-%y')
} @dates;
print "$_\n" for @sorted;
__DATA__
05-FEB-12
10-MAR-11
22-AUG-11
26-FEB-12
10-NOV-12
07-JUN-11
20-APR-12
19-DEC-12
17-JAN-11
25-NOV-11
28-FEB-11
04-SEP-11
03-DEC-12
16-SEP-12
31-DEC-11
08-JUN-11
22-JUN-12
02-AUG-12
23-SEP-11
14-MAY-11
輸出
17-JAN-11
28-FEB-11
10-MAR-11
14-MAY-11
07-JUN-11
08-JUN-11
22-AUG-11
04-SEP-11
23-SEP-11
25-NOV-11
31-DEC-11
05-FEB-12
26-FEB-12
20-APR-12
22-JUN-12
02-AUG-12
16-SEP-12
10-NOV-12
03-DEC-12
19-DEC-12
在這裏使用[Schwartzian變換](http://en.wikipedia.org/wiki/Schwartzian_transform)可能是一個好主意。 (decorate-sort-undecorate) –
Schwartzian變換是一種優化,優化只應用於運行速度不夠快的代碼。它將大大增加代碼量,並且對初學程序員來說也是堅不可摧的。 – Borodin
@BradGilbert:比手寫Schwartzian更好,只需使用'List :: UtilsBy'' sort_by';即: nsort_by {Time :: Piece-> strptime($ _,'%b-%d-%y')} @dates – LeoNerd
這裏是一個可能的方式做到這一點只使用基本的Perl(無模塊):
#! perl -w
use strict;
my @dates = ('19-FEB-12', '15-APR-12', '13-JAN-11');
# map month names to numbers
my %monthnum = (
'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4,
'MAY' => 5, 'JUN' => 6, 'JUL' => 7, 'AUG' => 8,
'SEP' => 9, 'OCT' => 10, 'NOV' => 11, 'DEC' => 12
);
# sort the array using a helper function
my @sorted_dates = sort { convert_date($a) cmp convert_date($b) } @dates;
print join(", ", @sorted_dates), "\n";
# outputs: 13-JAN-11, 19-FEB-12, 15-APR-12
exit(0);
# THE END
# converts from 19-FEB-12 to 120219, for sorting
sub convert_date
{
my $d1 = shift;
my $d2;
if ($d1 =~ /(\d{2})-([A-Z]{3})-(\d{2})/)
{
$d2 = sprintf("%02d%02d%2d", $3, $monthnum{$2}, $1);
}
else
{
die "Unrecognized format: $d1";
}
return $d2;
}
這依賴於你的日期被正確格式化,但添加更多驗證應該是微不足道的。
使用DateTime模塊; 或使用帶月份選項的排序命令(* nix); 或將dd-mmm-yyyy轉換爲yyyymmdd然後進行排序;
[你嘗試過什麼(http://whathaveyoutried.com),到底是什麼? – 2012-06-11 21:27:53