2012-06-11 39 views
0

我需要幫助在perl中排序。我有這種格式的日期數組。 DD-MMM-YY。例19-FEB-12。在Perl中排序日期

我已經花了相當多的時間,但無法得到它的工作。我對perl也很陌生。任何數量的幫助表示讚賞。謝謝!!

+3

[你嘗試過什麼(http://whathaveyoutried.com),到底是什麼? – 2012-06-11 21:27:53

回答

-2

完全從頭開始:

打印輸出:

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"; 
} 
+0

我很驚訝這被標記爲接受的答案。 Borodin使用Time :: Piece(這是一個核心Perl模塊)的答案比較好。 –

3

一個簡單的方法是將日期轉換爲可按字典順序排序的YYYYMMDD格式。

請注意,MM應該是以兩位數字表示的月份。

1

您可以使用核心模塊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 
10

這可以使用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 
+0

在這裏使用[Schwartzian變換](http://en.wikipedia.org/wiki/Schwartzian_transform)可能是一個好主意。 (decorate-sort-undecorate) –

+4

Schwartzian變換是一種優化,優化只應用於運行速度不夠快的代碼。它將大大增加代碼量,並且對初學程序員來說也是堅不可摧的。 – Borodin

+0

@BradGilbert:比手寫Schwartzian更好,只需使用'List :: UtilsBy'' sort_by';即: nsort_by {Time :: Piece-> strptime($ _,'%b-%d-%y')} @dates – LeoNerd

1

這裏是一個可能的方式做到這一點只使用基本的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; 
} 

這依賴於你的日期被正確格式化,但添加更多驗證應該是微不足道的。

0

使用DateTime模塊; 或使用帶月份選項的排序命令(* nix); 或將dd-mmm-yyyy轉換爲yyyymmdd然後進行排序;