수색…


소개

일의 목록을 정렬을 위해, 펄은 하나의 기능, 당연히 불리는이 sort . 숫자, 모든 인코딩 수의 문자열, 중첩 된 데이터 구조 또는 객체 등 모든 종류의 항목을 정렬 할 수있을만큼 유연합니다. 그러나 유연성으로 인해 사용법을 배울 수있는 몇 가지 트릭과 관용구가 있습니다.

통사론

  • 정렬 SUBNAME LIST
  • 정렬 BLOCK LIST
  • 정렬 목록

기본 어휘 정렬

@sorted = sort @list;

@sorted = sort { $a cmp $b } @list;

sub compare { $a cmp $b }
@sorted = sort compare @list;

위의 세 가지 예는 완전히 똑같습니다. 비교 함수 나 블록을 제공하지 않으면, sort 는 당신이 어휘 적으로 정렬 된 오른쪽리스트를 원한다고 가정합니다. 이것은 예측 가능한 순서로 데이터가 필요하고 언어의 정확성에 신경 쓰지 않는 경우에 보통 원하는 형식입니다.

sort@list 에있는 항목 쌍을 Comparator 함수로 @list 합니다.이 함수는 어느 항목이 더 큰지 sort 합니다. cmp 연산자는 문자열에 대해 이것을 수행하는 반면 <=> 는 숫자에 대해 동일한 작업을 수행합니다. 비교기는 평균 n * log ( n ) 배로 매우 자주 호출됩니다. n 은 정렬 될 요소의 수이므로 빠른 것이 중요합니다. 이것은 sort 가 미리 정의 된 패키지 전역 변수 ( $a$b )를 사용하여 적절한 함수 매개 변수 대신 블록이나 함수와 비교할 요소를 전달합니다.

당신이 경우 use locale , cmp 그것을 정렬합니다, 예를 들어, 계정으로 로케일 고유의 배열 순서를 취 Å 같은 A 덴마크 로케일에서하지만 후 Z 영어 또는 독일어 하나에. 그러나 더 복잡한 유니 코드 정렬 규칙을 고려하지 않으며 주문에 대한 제어도 제공하지 않습니다. 예를 들어 전화 번호부는 사전과 다르게 정렬되는 경우가 많습니다. 이 경우 Unicode::Collate 및 특히 Unicode::Collate::Locale 모듈을 사용하는 것이 좋습니다.

숫자 정렬

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

$a$b<=> 연산자와 비교하면 값이 문자 그대로 비교되지 않도록 수치 적으로 비교할 수 있습니다.

역순 정렬

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

내림차순으로 항목을 정렬 $a 것은 비교기 블록에서 $b$b 를 바꾸는 것만으로 간단히 달성 할 수 있습니다. 그러나 약간의 속도가 느리지 만 별도의 reverse 명확히하는 사람들이 있습니다.

Schwartzian 변환

이것은 아마도 항목의 정렬 순서가 값 비싼 함수에 의존하는 Perl의 함수 프로그래밍 기능을 사용하는 정렬 최적화의 가장 유명한 예제 일 것입니다.

# What you would usually do
@sorted = sort { slow($a) <=> slow($b) } @list;

# What you do to make it faster
@sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, slow($_) ] }
@list;

첫 번째 예제의 문제점은 비교기가 매우 자주 호출되고 느린 함수를 계속 반복하여 사용하여 값을 다시 계산한다는 점입니다. 일반적인 예는 파일 이름별로 파일 이름을 정렬하는 것입니다.

use File::stat;
@sorted = sort { stat($a)->size <=> stat($b)->size } glob "*";

이것은 작동하지만 기껏해야 비교 당 두 번의 시스템 호출의 오버 헤드가 발생합니다. 최악의 경우 한 번 비교할 때마다 두 번씩 디스크에 가야하고 그 디스크는 다른 쪽의 오버로드 된 파일 서버에있을 수 있습니다. 행성.

Randall Schwartz의 트릭을 입력하십시오.

Schwartzian Transform은 기본적으로 bottom-to-top의 세 가지 함수를 통해 @list . 첫 번째 map 은 각 항목을 원본 항목의 두 요소 목록과 느린 기능의 결과를 정렬 키로 변환하므로이 마지막 단계에서는 각 요소에 대해 slow() 한 번만 호출했습니다. 다음 sort 은 목록을보고 정렬 키에 간단하게 액세스 할 수 있습니다. 정렬 키는 신경 쓰지 않지만 원래 요소 만 정렬 된 순서로 필요하기 때문에 최종 map@sort 에서받은 이미 정렬 된 목록에서 두 요소 목록을 @sort 첫 번째 멤버 목록을 반환합니다 .

대소 문자를 구분하지 않는 정렬

sort 대소 문자를 무시하게 만드는 전통적인 기법은 비교를 위해 문자열을 lc 또는 uc 에 전달하는 것입니다.

@sorted = sort { lc($a) cmp lc($b) } @list;

이것은 Perl 5의 모든 버전에서 작동하며 영어로는 충분합니다. uc 또는 lc 를 사용하는지 여부는 중요하지 않습니다. 그러나 그리스어 나 터키어 같은 대문자와 소문자가 1 : 1로 대응하지 않으므로 uclc 것을 사용 하느냐에 따라 다른 결과를 얻을 수 있습니다. 따라서, 펄 5.16 이상에서는 기능이라고 접는 경우가 fc 이러한 문제를 방지, 다 언어 정렬이를 사용해야합니다 그래서 현대 :

@sorted = sort { fc($a) cmp fc($b) } @list;


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow