이전 포스팅에서 배열과 리스트에 대한 사용 방법을 알아봤었습니다.
이번에는 키와 값으로 만들어 사용할 수 있는 해시에 대해 알아보겠습니다.
해시 함수란
해시 란 연상 배열이라고도 불리며, [키]와 [값]을 한 세트로 해서 관련되어 있는 배열입니다.
단, 배열 자체에 순서가 부여되지 않은 것이 특징 입니다.
해시 변수명은 %(퍼센트) + 영문자로 시작하며 그 이후는 숫자 영문자 그리고 언더바(_)를 사용할 수 있습니다.
그리고 대문자 소문자를 구별합니다.
%a 와 %A는 별개로 취급합니다.
해시 변수의 조작
해시 변수는 키와 값을 세트로 해서 숫자나 문자열을 대입합니다.
%fruit = ("red" => "apple", "yellow" => "banana");
위의 경우 red(키)와 apple(값)으로 세트를, yellow(키)와 banana(값)으로 세트를 이뤄 각각 %fruit에 대입되었습니다.
다음과 같이도 기술할 수 있습니다.
$fruit{"red"} = "apple";
$fruit{"yellow"} = "banana";
해시 변수의 각 요소에는 [키]을 지정하는 것으로 [값]에 접근할 수 있습니다.
%fruit = ("red" => "apple", "yellow" => "banana", "purple" => "grape");
print "$fruit{'red'}";
참고로 [키] 문자열이 모두[숫자, 영문자, 언더바]의 경우에는 쿼테이션에의해 쿼터를 생략 가능합니다.
키 쿼테이션 생략 예 -1
%fruit = (red => "apple", yellow => "banana", purple => "grape");
# 키 쿼테이션 생략 예 -2
print "$fruit{red}";
> apple
해시 함수
해시를 조작하기 위한 함수로 다음과 같은 함수가 있습니다.
함수 | 내용 |
keys | 모든 키를 취득 |
values | 모든 값을 취득 |
each | 1세트의 키와 값을 취득 |
delete | 특정 요소를 삭제 |
keys
모든 [키]를 취득 합니다.
단, 취득한 배열은 순서는 일정하지 않습니다.
이것은 해시는 순서가 부여되지 않은 배열이기 때문입니다.
%fruit = (red => "apple", yellow => "banana", purple => "grape");
@key = keys %fruit;
print @key;
> red yellow purple
values
모든 [값]을 취득합니다.
키 함수와 동일하게 취득 순서는 일정하지 않습니다.
%fruit = (red => "apple", yellow => "banana", purple => "grape");
@val = values %fruit;
print @val;
> apple banana grape
each
1세트의 [키]와 [값]을 취득합니다.
%fruit = (red => "apple", yellow => "banana", purple => "grape");
($key, $val) = each %fruit;
print "$key : $val";
> red : apple
하지만 위의 예는 어느 세트가 취득되었는지 알 수 없습니다.
그리고 하나의 세트만 취득되기 때문에 보통 each를 사용하는 경우는 다음과 같이 while 구문과 병행해서 하는 형식으로 사용합니다.
%fruit = (red => "apple", yellow => "banana", purple => "grape");
# 해시 요소를 모두 출력
while( my ($key, $val) = each %fruit) {
print "$key : $val \n";
}
> purple : grape
> red : apple
> yellow : banana
delete
특정의 요소를 삭제
변수 키를 지정하는 것으로 그 키에 해당하는 키와 값을 해시에서 삭제합니다.
%fruit = (red => "apple", yellow => "banana", purple => "grape");
# 요소를 삭제 (yellow - banana)
delete $fruit{yellow};
# 해시에 남은 요소를 모두 출력
while( my ($key, $val) = each %fruit) {
print "$key : $val \n";
}
> purple : grape
> red : apple
참고로 위에 delete 함수는 특정 요소를 삭제하는 경우이지만, 모든 요소를 삭제하는 경우에는 공란 리스트를 대입하면 모든 요소가 삭제됩니다.
%fruit = ();
하지만, 위의 경우는 배열 안이 공란으로 된것으로 배열이 정의되어 있는 상태입니다.
만약 미정의 상태로 하고 싶은 경우에는 undef 함수를 사용합니다.
undef %fruit;
해시 자르기
배열 변수의 자르기와 동일하게, 해시 자르기를 사용하면 각 요소의 집합에 접근할 수 있습니다.
예를 들어 다음과 같은 멤버의 연령 데이터가 있습니다.
%age = (tom => 21, mike => 19, kent => 25, nancy => 17);
이것을 자르기를 이용하면, 다음과 같이도 기술할 수 있습니다. 선두는 %가 아닌 @를 사용합니다.
@age{ qw(tom mike kent nancy) } = (21,19,25,17);
다음으로는 연령을 변경해 보도록 하겠습니다.
use strict;
# 연령 데이터
my %age = (tom => 21, mike => 19, kent => 25, nancy => 17);
# tom과 mike의 연령을 변경
@age{ qw(tom mike) } = (22,20);
# 해시의 모든 요소를 출력
while (my ($key, $val) = each %age ) {
print "$key : $val \n";
}
> tom : 22
> nancy : 17
> mike : 20
> kent : 25
그리고 자르기를 이용하여 임의의 요소를 출력해보도록 하겠습니다.
use strict;
# 연령 데이터
my %age = (tom => 21, mike => 19, kent => 25, nancy => 17);
# kent과 nancy의 연령을 취득
my @data = @age{ qw(kent nancy) };
# 취득 데이터를 출력
print @data;
> 25 17
해시를 대입 순서대로 나열
해시 배열은 순서대로 나열되지 않습니다.
하지만 [키]나 [값]을 순서대로 취득하고 싶은 경우가 있습니다. 이럴 때는 Tie::IxHash 모듈을 이용해서 구현할 수 있습니다.
매우 편리한 모듈이기에 한 번 살펴보도록 하겠습니다.
Tie::IxHash 사용법은 반드시 해시를 호출하기 전에 tie 함수로 관련지어주는 것입니다.
use strict;
use Tie::IxHash;
# %hash를 tie와 관련 지어줌
tie ( my %hash, 'Tie::IxHash' );
# 해시에 대입
%hash = ( Sum => 0,
Mon => 1,
Tue => 2,
Wed => 3,
);
# 해시의 모든 요소를 출력
while (my ($key, $val) = each %hash ) {
print "$key : $val \n";
}
> Sum : 0
> Mon : 1
> Tue : 2
> Wed : 3
위와 같이 모든 키와 값으 대입 순서대로 출력할 수 있습니다.
참고로 Tie::IxHash 모듈은 표준 모듈은 아닙니다. 인스톨이 필요합니다.
다차원 해시
해시는 배열과 동일하게 다차원으로 이용할 수 있습니다.
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
중괄호({}) 부분을 하나의 스칼라로 이해하면 조금 더 이해에 도움이 될 거라 생각됩니다.
%hash에 키[A]에 해당하는 값 안의 키[a]의 값[1]에 접근하는 것으로는 다음과 같이 인덱스를 이용하여 접근할 수 있습니다.
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
print $hash{A}{a};
> 1
리퍼 런스를 사용해서 키[A]에 해당하는 값(배열)을 출력하는 방법은 다음과 같습니다.
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
while ( my ($key, $val) = each %{$hash{A}} ) {
print "$key : $val \n";
}
> b : 2
> a : 1
> c : 3
%hash 안의 모든 키와 값을 출력하는 방법은 다음과 같습니다.
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
foreach my $tmp ( keys %hash ) {
while ( my ($key, $val) = each %{$hash{$tmp}} ) {
print "$key : $val\n";
}
}
> f : 6
> e : 5
> d : 4
> c : 3
> b : 2
> a : 1
%hash에 해당하는 2차원 키와 값을 추가하는 방법은 다음과 같습니다.
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
# 키[C]와 값을 추가
$hash{C} = { g => 7, h => 8, i => 9 };
while ( my ($key, $val) = each %{$hash{C}} ) {
print "$key : $val \n";
}
> h : 8
> i : 9
> g : 7
# 특정 키에 해당하는 값에 요소를 추가
%hash = (
A => { a => 1, b => 2, c => 3 },
B => { d => 4, e => 5, f => 6 },
);
# 키[A]에 값에 요소를 추가
$hash{A}{x} = 7;
while ( my ($key, $val) = each %{$hash{A}} ) {
print "$key : $val \n";
}
> b : 2
> a : 1
> x : 7
> c : 3
댓글