Tips in Action‎ > ‎배열과 Hash‎ > ‎

배열을 해쉬로 변환하기 - map 함수

전종필

스크립트를 만들다 보면, 간혹, 배열을 해쉬로 변환해야 할 경우들이 있습니다. 예를 들면, 배열의 각 요소가 중복되지 않도록 같은 것을 솎아내는 경우입니다.

@arr = qw( aa bb aa cc dd bb aa ee );
%hash = map { ($_, 1) } @arr;
@arr = sort keys %hash;
print "@arr\n";
위의 경우 출력되는 내용은 aa bb cc dd ee입니다.
map 함수는 배열(위의 경우 @arr)의 각 요소에 대해서 블록 {}안의 내용(위의 경우 ($_, 1))을 실행하여 그 결과들의 합을 반환합니다. 블록안의 내용을 적용할 때, 배열의 각 요소는 매번 $_ 변수에 대입됩니다. 따라서 위에서 %hash = map { ($_, 1) } @arr;

%hash = ( ( 'aa', 1 ), ( 'bb', 1 ), ( 'aa', 1 ), ( 'cc', 1 ),
	  ( 'dd', 1 ), ( 'bb', 1 ), ( 'aa', 1 ), ( 'ee', 1 ) );
와 같은 의미가 됩니다. 물론 위의 경우 원래 배열의 요소들의 순서가 흐트러지기는 하지요.

또다른 예로, 간단한 파일 분석기를 만들 수도 있습니다.
파일 myprog.conf는 키와 값을 '=' 부호로 분리하여 가지고 있습니다. 다음과 같다고 하죠.


datadir=/data
user=nouser
min=1
max=9999999
이 데이터를 해쉬 %conf에 저장하려 합니다.
다음과 같은 코드를 사용하면 됩니다.

open(FH, 'myprog.conf') || die $!;
my %conf = map { chomp; split(/=/,$_,2); } <FH>;
close FH;

foreach my $key ( keys %conf ) {
	print "$key : $conf{$key}\n";
}
map 함수의 블록 내부는 어떤 내용도 들어갈 수 있습니다. 가장 마지막에 남기는(evaluate) 값이 최종 결과에 반영이 됩니다. 위의 경우는 chomp함수로 먼저 각 줄에 붙어 있는 "\n" 값을 떼어낸 후 마지막으로 split(/=/,$_,2);이 반환하는 값을 남기게 됩니다.
파일 핸들을 목록형 문맥(list context)에서 사용하면 프로그램은 파일 핸들을 마치 배열처럼 여깁니다. 따라서 위와 같이 map 함수의 블록 뒤에 파일핸들을 직접 사용할 수 있습니다.
만일 위와 같은 map 사용이 헷갈리시면

my @array = ;
my %conf = map { chomp; split(/=/,$_,2); } @array;
라고 하여도 무방합니다.

map 함수는 물론 배열을 해쉬로 바꾸기 위해서만 사용하는 것은 아닙니다. 또 다른 사용에 대해서는 다른 기회(아마도 Tips에..)에 보여드릴 수 있지 않을까요? 

Comments