2009-07-27 2 views
2

나는 dd/mm/yyyy 날짜 목록을 해시에 저장하여 순차적으로 날짜 순서대로 인쇄해야합니다. 다음은 관련 발췌 부분입니다.Perl을 사용하여 월별로 dd/mm/yyyy 형식의 날짜를 정렬하려면 어떻게해야합니까?

use feature 'say'; 

for my $date (sort {$a cmp $b} keys %data) { 
    say $date; 
} 

이 출력 :

16/07/2008 
16/08/2008 
16/09/2008 
17/07/2008 
17/08/2008 
17/09/2008, etc. 

내가 필요로하는 경우 :

16/07/2008 
17/07/2008 
16/08/2008 
17/08/2008 
16/09/2008 
16/09/2008, etc. 

어떻게 이것을 달성 할 수 있습니까?

답변

7

포맷이 경질 10 개 문자 인 경우, (을 perlfunc의 정렬에 기재되어 있음)) (정렬 How do I sort an array by (anything)?


공급을 비교 함수 perlfaq4의 답 가입일

sort { substr($a,3,2) cmp substr($b,3,2) } @dates; 
+0

나는 간결함을 좋아한다! – Zaid

+0

Schwartzian Transform을 수행해야합니다. 각 요소에 대해 두 번 비교할 부분을 다시 계산할 필요가 없습니다. 특히 형식이 딱딱하지 않은 경우. – dlamblin

+3

조숙 한 최적화는 모든 악의 뿌리입니다. "substr"이 해시 검색보다 빠르거나 빠를 것이라고 생각하지 않습니까? – jrockway

7

구문 분석 및 분류 : 나는 객체가 아닌 의미없는 문자열을 작업 할 때부터 아마 날짜 시간은,하지만, 사용하는 것이

sub get_month { 
    my $date = shift; 
    my ($d, $m, $y) = split m{/}, $date; 
    return $m; 
} 

sort { get_month($a) <=> get_month($b) } @dates; 

:

my $parser = DateTime::Format::Natural->new(format => 'dd/mm/yyyy'); 
sort map { $parser->parse_datetime($_) } @dates; 
+1

달콤한. 따라서 sort 명령 내에 서브 루틴을 내장 할 수 있습니다. 나는 그걸 모르고 ... – Zaid

+0

"월별 순서"- 나는 그 날을 inint 달 단위로 의미하는 것으로 간주하고 "월별"은 실제로 한 달 안에 달을 의미한다고 가정했다. – ysth

+0

@ysth : 맞습니다. jrockway의 솔루션은 그렇게하지 않지만 올바른 방향으로 나를 가리켰습니다. – Zaid

12

당신은 그것이 Schwartzian Transform를 사용 할 수있는, 좋아요 :

각 키는입니다. 0이고 첫 번째 요소가 키이고 두 번째 요소가 중간 필드 인 / 인 익명 배열에 저장합니다. 그런 다음 배열의 두 번째 요소로 정렬하고 map을 사용하여 원래 키 목록을 가져옵니다.

2

:

@list = sort { $a <=> $b } @list; 

기본 정렬 함수는 cmp, 문자열 비교, w hich는 (1, 2, 10)을 (1, 10, 2)로 분류합니다. < =>은 수치 비교 연산자입니다.

정렬 기능을 원하는 부분을 꺼내기 위해 복잡한 기능이 필요한 경우 정렬 기능에서 처리하지 마십시오. 정렬 BLOCK은 동일한 요소에 대해 여러 번 호출 될 수 있기 때문에 먼저 꺼내십시오. 다음은 각 항목의 첫 번째 숫자 다음에 나오는 첫 단어를 빼내어 대소 문자를 구분하지 않는 방법의 예입니다. 또한 찌언 변환로 알려왔다 트릭을 사용하여,이 방법을 쓸 수

@idx =(); 
for (@data) { 
    ($item) = /\d+\s*(\S+)/; 
    push @idx, uc($item); 
    } 
@sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ]; 

는 :

@sorted = map { $_->[0] } 
    sort { $a->[1] cmp $b->[1] } 
    map { [ $_, uc((/\d+\s*(\S+)/)[0]) ] } @data; 

여러 필드를 정렬해야하는 경우, 다음과 같은 패러다임에 유용합니다.

@sorted = sort { 
    field1($a) <=> field1($b) || 
    field2($a) cmp field2($b) || 
    field3($a) cmp field3($b) 
    } @data; 

위의 주어진 키의 사전 계산과 편리하게 결합 할 수 있습니다.

이 접근 방법에 대한 자세한 내용은 http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz에있는 "알고 싶었던 것보다 멀리있는 것"모음의 정렬 기사를 참조하십시오.

나중에 해시 정렬에 대한 perlfaq4의 질문을 참조하십시오.

관련 문제