Recent Posts
Recent Comments
Link
11-29 16:02
동글동글 라이프
역 해시 (Reverse Hash) 본문
- Hash
사용되는 키(Key) 와 값(value)을 가지는 구조인 hash는 Perl에서 아래와 같이 구성된다.
Output:
|
hash1과 hash2는 표현방법이 다를 뿐 같은 값을 담고 있으며
일반전인 hash 구성 방법이다.
a 라는 key 값에 1이라는 값이 쌍으로 대입되어 있으며,
이러한 해시구조는 데이터를 관리하거나 표현할 때 유용하게 사용이 된다.
Key 값을 통해서 Value 값을 찾는것은 매우 간단하다.
Hash의 특정 요소를 접근하려면 해쉬의 키를 { } 을 사용하여 원하는 요소를 접근할 수 있다.
위의 예제에서 key값이 a인 값의 value를 알고 싶을 때
print $hash1{'a'}; # 1
라고 출력하면 1 이라는 결과값이 출력이 된다.
기본적으로 hash를 배우는 사람들은 여기서 만족을 한다.
하지만 질문을 하나 던져 보도록 하자.
Value값에 따라 Key 값을 구하고 싶을 때는 어떻게 하는 것이 좋을까?
첫 번째 답안 제출 : 해당 값(Value)를 hash안에서 Key 값과 일치하는것을 모두 검색해서 찾으면 Get !!
허접한 설명 : 검색자체에 시간을 너무 많이 뺏김으로 좋은 알고리즘이 아니다. 시간은 생명!!
두 번째 답안 제출 : $hash{'키'} 니깐... <--> $hash1{'값'} 맞나염 ????
허접한 설명 : 넌 hash가 뭔지도 모르는 놈이다 -_- 펄독보고 내공 좀 더 쌓아라...
세 번째 답안 제출 : 역 해시를 만들면 됩니다.
허접한 설명 : Oh!! Good Job~
그렇다... 해시를 처음 만들 때 역해시도 같이 만들어 놓으면 되는것이다.
여기서 역 해시란 원래 해시에서 Key와 Value가 바뀌어서 들어간 해시를 뜻한다.
- Perl hash 문제1 ! 역해시를 만들어주는 코드를 작성하여라. |
지나가는 손님1 : my %rhash = reverse %hash; # 한방에 해결? 후욱후욱 내공 주삼
허접한 설명 : 상당히 좋은 방법이다. 일단 hash란 배열처럼 차례대로 데이터를 넣으면
첫번째는 key 두번째는 value로 키와 값이 쌍으로 대입되므로 reverse로 뒤집어 주기만 하면,
간단하게 역해시가 완성이 된다.
나 펄좀 공부했삼 : 태클!! 저런식으로 역해시를 만들때 한가지 문제점이 있다. Key 값은 중복 될 수 없으니
역해시를 만들때 value를 키로 사용하면 값을 잃어버릴 수도 있게 된다.
문제점을 파악하였는가?
나쁘지 않은 발상 및 코드지만... 중복된 값이 없다는 가정하에 작성 될 수 있는 코드이다.
앞서 작성한 예제를 코드에 적용시켜 역해시를 만들어 보겠다.
Output:
|
2 = c 부터 차례차례 reverse가 되었을 때,
1 = b 의 값을 1 = a 로 값이 치환되어 버린것을 확인 할 수 있다.
여기서 Perl 커뮤니티의 대부 a3r0님의 문제 작렬!!
- Perl hash 문제2 ! %hash = ( a=>1, b=>1, c=>2); 을 역해시화 하면 %rhash = ( 1=>['a','b'], 2=>['c'] ); 처럼 되게 만들어보아라! |
역해시는 이와 같이 값이 중복 될 때는 기존의 key를 익명 배열에 넣어서 Push 해 버리는 방법을 사용하여
중복된 value가 있더라도 그 값이 유실 되지 않도록 할 수 있다.
일단 직접 만들어 보는것이 좋지만...
모범답안을 공개하도록 한다.
처음 답안을 공개했던 Luz♡lunA 님의 코드
use strict;
use warnings;
my %hash = ( a=>1, b=>1, c=>2);
my %rhash;
print "print hash\n";
while ( my ($key,$value) = each %hash ) {
print "$key : $value\n";
push @{$rhash{$value}},$key;
}
print "print reverse hash\n";
while ( my ($key,$value) = each %rhash ) {
print "$key : @{$value} \n";
}
|
Output:
print hash
c : 2
a : 1
b : 1
print reverse hash
1 : a b
2 : c
|
@{배열래퍼런스} 로 디 레퍼런스 하는 부분에서 깔끔하게 처리해 주셨다.
뒤이어 pung96님의 답안 소스를 조금더 perlish 하게 꾸며 주었다.
use strict;
use warnings;
my %hash = ( a=>1, b=>1, c=>2);
my %rhash;
my ($k,$v);
push @{$rhash{$v}}, $k while ( ($k, $v) = each %hash );
print "print reverse hash\n";
while ( my ($key,$value) = each %rhash ) {
print "$key : @{$value} \n";
}
|
Output:
print reverse hash
1 : a b
2 : c |
뒤늦게 keys 함수를 사용한 keedi님의 깔끔한 답변~
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %hash = ( a => 1, b => 1, c => 2 );
my %rhash;
push @{ $rhash{$hash{$_}} }, $_ for keys %hash;
print Dumper(\%hash);
print Dumper(\%rhash);
|
Output:
$VAR1 = {
'c' => 2,
'a' => 1,
'b' => 1
};
$VAR1 = {
'1' => [
'a',
'b'
],
'2' => [
'c'
]
};
|
코어모듈인 Date::Dumber를 사용하여 보기좋게 출력하였다.
a3r0님은 Data::Dump 모듈이 더 출력이 깔끔하다고 이야기 하셨지만
코어모듈이 아니라는 단점이...
뭐.. 모듈 설치야 간단하지만 Codepad에서 Output이 출력이 되지 않는다는 점이 아쉽다.
자 그러면... 여기까지 왔으면 조금만 더 힘을 내자.
이렇게 만든 역해시를 다시 원래 해시로 돌려주는 방법은 무엇일까?
- Perl hash 문제3 ! %rhash = ( 1=>['a','b'], 2=>['c'] ); 를 %hash = ( a=>1, b=>1, c=>2 ); 로 만들어라. |
본인의 경우는 2중루프를 돌려 이 문제를 풀었다.
use strict;
use warnings;
use Data::Dumper;
my %hash = ( a => 1, b => 1, c => 2 );
my %rhash;
push @{ $rhash{$hash{$_}} }, $_ for keys %hash;
my ($k,$v);
my %dhash;
foreach my $key( keys %rhash){
foreach(@{$rhash{$key}}){
$dhash{$_} = $key;
}
}
print Dumper(\%hash);
print Dumper(\%rhash);
print Dumper(\%dhash);
|
Output:
$VAR1 = {
'c' => 2,
'a' => 1,
'b' => 1
};
$VAR1 = {
'1' => [
'a',
'b'
],
'2' => [
'c'
]
};
$VAR1 = {
'c' => '2',
'a' => '1',
'b' => '1'
};
|
각각의 무명배열의 값을 따라간 뒤 key와 value를 다시 넣어주는 작업을 하였는데,
perl 커뮤니티에서 이러한 답을 내면 --(점수를 잃는의미)를 받게 된다.
모범답안을 제시하자면
a3r0님의 해시 슬라이스 무공을 사용한... 답안;;
use strict;
use warnings;
use Data::Dump qw/dump/;
my %rhash = ( 1=>['a','b'], 2=>['c'] );
my %hash;
@hash{ @{$rhash{$_}} }=($_)x@{$rhash{$_}} for keys %rhash;
dump(%hash);
|
결과값 : ("c", 2, "a", 1, "b", 1)
dump함수가 %hash를 이쁘게 출력시켜준다.
다음번엔 여기서 사용된 해시 슬라이스 신공에 대해서 한번 블로깅을 해야 할듯...
역해시를 구현해야 하시는 분들께 좋은 자료가 되길!
Good Job~ ^^/
'개발자 이야기 > Perl' 카테고리의 다른 글
Morse (모스 부호) (9) | 2009.01.29 |
---|---|
Perl로 짠 IRC Bot (1) | 2009.01.13 |
irc 로그 분석 (0) | 2009.01.08 |
정규 표현식에 대하여... (6) | 2008.12.29 |
플래시 게임을 즐기자. (6) | 2008.12.11 |
Comments