Perl 해시 hash 사용 방법 예제

이전 포스팅에서 배열과 리스트에 대한 사용 방법을 알아봤었습니다.

이번에는 키와 값으로 만들어 사용할 수 있는 해시에 대해 알아보겠습니다.

 

해시 함수란

해시 란 연상 배열이라고도 불리며, [키]와 [값]을 한 세트로 해서 관련되어 있는 배열입니다.

단, 배열 자체에 순서가 부여되지 않은 것이 특징 입니다.

해시 변수명은  %(퍼센트) + 영문자로 시작하며 그 이후는 숫자 영문자 그리고 언더바(_)를 사용할 수 있습니다.

그리고 대문자 소문자를 구별합니다.

%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 

댓글