IDL/Data Type & Format

해쉬(Hash) 자료형에 관하여

이상우_IDL 2025. 6. 10. 15:11
728x90

IDL 8.0 버전에서부터 지원되기 시작한 자료형(Data Type)들인 리스트(List)와 해쉬(Hash)에 관하여 순차적으로 소개하고 있습니다. 먼저 리스트(List) 자료형에 관해서는 앞서 관련 게시물들(링크1, 링크2)을 통하여 소개한 바 있고, 이제 해쉬(Hash) 자료형에 관하여 살펴보기로 하겠습니다. 이미 소개된 리스트(List)와 마찬가지로 해쉬(Hash)도 일종의 복합형 자료형의 성격을 띈다고 볼 수 있습니다. 다만 해쉬의 경우는 일종의 사전(Dictionary)와 같은 성격을 띕니다. 즉 어떤 원소값이 있으면 이 값에 대응되는 키(key)라는 것이 반드시 존재하여, 각 원소는 키-원소값의 쌍(key-value pair)의 형태가 되어야 합니다. 이러한 '사전'과 같은 형태의 자료형은 이미 다른 프로그래밍 언어들에서도 널리 차용하고 있는 개념이기도 합니다. 먼저 해쉬의 전반적인 특성들을 살펴보면 다음과 같습니다.

 

1. 해쉬 개체 내의 원소들은 순서에 따른 정렬이라는 개념이 없으며, 인덱스(index)가 아닌 키(key)를 통해서만 그 원소값에 접근할 수 있다.

2. 해쉬 개체 내의 원소들은 나중에도 추가 및 삭제가 가능하므로, 해쉬 개체의 크기는 항상 유연하게 변할 수 있다.

3. 해쉬 개체 내의 원소들 자체도 그 값이나 자료형이 언제나 변경 가능하며, 이에 따른 퍼포먼스상의 손해는 전혀 없다.

 

아마 1번을 제외하면 리스트와 매우 유사하다는 점을 발견할 수 있습니다. 해쉬 개체를 생성하려면 HASH 함수를 사용하면 됩니다. 해쉬 개체내의 원소들은 어떤 자료형이든 가능하며, 단일값이든 배열이든 모두 가능합니다. 심지어 구조체(Structure), 포인터(Pointer), 리스트(List) 및 다른 해쉬(Hash) 개체도 원소가 될 수 있습니다. 예를 들어서 다음과 같이 원소의 갯수가 4인 해쉬 개체를 하나 생성해봅시다.

 

IDL> hs = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> PRINT, N_ELEMENTS(hs)
           4
IDL> PRINT, hs['one']
      1.00000
IDL> PRINT, hs['red']
     255       0       0

IDL> PRINT, hs['pi']
      3.14159

IDL> PRINT, hs[10]
     100

 

여기서 HASH 함수를 사용하여 해쉬 개체를 생성하는데 있어서 그 구성원소들은 (키1,원소값1, 키2, 원소값2, 키3, 원소값3, 키4, 원소값4)와 같은 방식으로 정의하였습니다. 이 때 키(Key)에 해당되는 값은 문자 또는 숫자만 가능합니다. 해쉬 개체의 원소값들에 접근하려면 해당 키 값을 마치 인덱스와 같은 느낌으로 사용하면 됩니다. 따라서 첫번째 원소인 1.0이란 값에 대한 접근 방법은 hs['one']이 됩니다. 그리고 앞서 언급했듯이 해쉬 개체 내의 원소값들 사이에는 '순서'라는 개념은 없습니다. 기존의 배열, 구조체, 리스트 등에서 원소들의 순서에 해당되는 인덱스로 원소값에 접근하였던 것과는 전혀 다릅니다. 따라서 해쉬 개체 내의 원소값들에 접근하기 위해서는 키 값이라는 일종의 '인식표'를 사용해야 한다는 것을 유념해야 합니다. 그리고 위의 내용에서 해쉬 개체 hs에 대하여 N_ELEMENTS 함수를 적용한 결과 값이 4가 됨을 주목해야 합니다. 이것은 해쉬 개체 hs가 4개의 쌍(key-value pair)들로 구성되어 있다는 의미입니다. 얼핏 보기에는 8개의 값들이 존재하는 것처럼 보일 수도 있지만, 해쉬에서는 모든 원소가 쌍(pair)이라는 단위로 인식되기 때문에 이와 같이 4개의 쌍들로 구성되어 있는 것으로 간주됨을 유의해야 합니다.

 

해쉬를 생성할 때 키와 원소값들을 각각 미리 배열로 구성해놓고 이들을 HASH 함수의 인자로 사용할 수도 있습니다. 즉 앞서 정의했던 해쉬 개체를 다음과 같은 방식으로 정의해도 결과는 같습니다.

 

IDL> keys = LIST('one', 'red', 'pi', 10)
IDL> values = LIST(1.0, [255, 0, 0], !pi, 100)
IDL> hs = HASH(keys, values)
IDL> PRINT, N_ELEMENTS(hs)
           4

 

여기서는 키(Key)들로만 구성된 리스트 개체인 keys 그리고 원소값(Value)들로만 구성된 리스트 개체인 values를 각각 정의하고 이들을 HASH 함수에 투입하여 해쉬 개체 hs를 정의하였습니다. 개별 원소에 접근하려면 앞서 언급했듯이 키를 활용하면 된다는 것도 마찬가지입니다.

 

IDL> PRINT, hs['red']
     255       0       0

 

그런데 여기서는 키 값들로 구성된 리스트 개체인 keys를 활용하여 다음과 같이 접근하는 것도 가능합니다.

 

IDL> PRINT, hs[keys[1]]
     255       0       0

 

참고로 키(Key)를 문자값으로 정의할 경우에는 대소문자의 구분이 존재합니다. 위에서 정의한 hs에서 두번째 원소를 보면 키값이 'red'라는 문자로 되어 있습니다. 그런데 이 키에 해당되는 값에 접근하기 위하여 hs['Red']와 같이 명시하면, 그러한 키가 존재하지 않는다는 메시지가 뜨면서 에러가 발생하게 됩니다. 따라서 키(Key)가 문자일 경우 이를 인식하는데 있어서 대소문자의 구분이 있다는 점을 반드시 유의해야 합니다.

 

IDL> PRINT, hs['Red']
% Key does not exist: "Red"
% Execution halted at: $MAIN$          

 

이번에는 HASH 함수로 생성된 해쉬 개체에 대하여 여러가지 작업들을 할 수 있도록 해주는 메서드들(Methods)에 관하여 알아봅시다.

 

< HasKey 메서드 >

 

먼저 특정한 키(Key) 값이 해쉬 개체 내에 존재하는가 여부를 판단해주는 HasKey 메서드가 있습니다. 이 메서드를 사용하면 해당 키가 존재할 경우에는 1, 존재하지 않을 경우에는 0이란 값을 돌려줍니다. 앞서 정의했던 해쉬 개체인 hs에 대하여 HasKey 메서드를 적용해보면 결과는 다음과 같습니다.

 

IDL> PRINT, hs.HasKey('red')
       1
IDL> PRINT, hs.HasKey('blue')
       0

 

< Keys 메서드 >

 

Keys 메서드는 해쉬 개체 내에 존재하는 모든 키(Key) 값들을 추출하여 리스트(List) 개체의 형태로 돌려줍니다. 앞서 정의했던 해쉬 개체 hs에 대하여 Keys 메서드를 적용해보면 결과는 다음과 같습니다.

 

IDL> keys_ext = hs.Keys()
IDL> HELP, keys_ext
KEYS_EXT        LIST  <ID=10  NELEMENTS=4>
IDL> PRINT, keys_ext
one
red
pi
      10

 

< Remove 메서드 >

 

Remove 메서드는 해쉬 개체 내의 특정한 원소 또는 원소들을 제거하는 역할을 합니다. 그리고 제거된 대상 원소들을 따로 추출할 수도 있습니다. 제거의 대상은 키(Key)를 인자로 사용하여 명시합니다. 다음 예제를 봅시다.

 

IDL> hs = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> hs.Remove('one')
       1.0000000
IDL> PRINT, hs
red:      255       0       0
pi:        3.1415927
10:      100

 

여기서는 키가 'one'인 원소만 제거하였습니다. 출력된 결과를 보면 해당 원소가 삭제된 것을 알 수 있습니다. 다음과 같이 다수의 원소들을 한꺼번에 제거하는 것도 가능합니다.

 

IDL> hs = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> hs.Remove, ['one', 'pi']
IDL> PRINT, hs
red:      255       0       0
10:      100

 

< Values 메서드 >

 

Values 메서드는 해쉬 개체 내에 존재하는 모든 원소값들을 리스트(List) 개체의 형태로 돌려줍니다.

 

IDL> hs = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> values_ext = hs.Values()
IDL> HELP, values_ext
VALUES_EXT      LIST  <ID=19  NELEMENTS=4>
IDL> PRINT, values_ext
       1.0000000
     255       0       0
       3.1415927
     100

 

< 해쉬 개체들의 합성 >

 

두 개 이상의 독립적인 해쉬 개체들을 서로 합치는 것도 가능합니다. 이를 위해서는 + 연산자를 사용하면 되며, 그 결과는 기존의 구성 원소들을 모두 포함하는 새로운 해쉬 개체가 됩니다.

 

IDL> hs1 = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> hs2 = HASH(7, 'HM Son', 3, 'MJ Kim')
IDL> hs3 = hs1+hs2
IDL> HELP, hs3
HS3             HASH  <ID=22  NELEMENTS=6>
IDL> PRINT, hs3
one:        1.0000000
3: MJ Kim
red:      255       0       0
7: HM Son
pi:        3.1415927
10:      100

 

이와 같이 hs1과 hs2를 합쳐서 생성된 hs3은 총 6개의 구성원소들을 갖는 새로운 해쉬 개체가 됩니다.

 

< 해쉬와 구조체의 합성 >

 

해쉬 개체를 구조체(Structure)와 합쳐서 새로운 해쉬 개체로 생성하는 것도 가능합니다. 사실 해쉬는 그 성격상 구조체와 유사한 측면이 많습니다. 그래서 여기서는 소개를 안했지만 ToStruct라는 메서드를 이용하여 해쉬를 구조체로 변환할 수도 있습니다(이 내용은 IDL 도움말에서 HASH 함수에 관한 내용을 참조하시면 됩니다). 어쨌든 해쉬와 구조체를 합성하는 예제를 보면 다음과 같습니다.

 

IDL> hs = HASH('one', 1.0, 'red', [255, 0, 0], 'pi', !pi, 10, 100)
IDL> struct = {player:'JH Lee', number:51}
IDL> hs_new = hs+struct
IDL> HELP, hs_new
HS_NEW          HASH  <ID=26  NELEMENTS=6>
IDL> PRINT, hs_new
one:        1.0000000
red:      255       0       0
pi:        3.1415927
10:      100
PLAYER: JH Lee
NUMBER:       51

 

여기서는 해쉬 개체인 hs 그리고 구조체인 struct를 각각 정의한 다음 + 연산자를 사용하여 이 둘을 바로 합쳐서 hs_new라는 새로운 해쉬 개체인 hs_new가 잘 생성되었음을 확인할 수 있습니다.

 

< 해쉬 개체들 사이의 비교 >

 

EQ 연산자를 사용하여 해쉬 개체와 다른 해쉬 개체 사이의 비교 또는 해쉬 개체와 단일값 사이의 비교도 가능합니다. 만약 해쉬 개체들 사이의 비교를 하는 경우에는 다음 예제와 같이 두 해쉬 개체 내에 모두 존재하면서 키(Key)도 서로 같고 값(Value)도 서로 같은 항목들에 대한 키 값들을 얻을 수 있습니다.

 

IDL> hs1 = HASH('key1', 1, 'key2', 2, 'key3', 3, 'anotherkey', 3.14)
IDL> hs2 = HASH('key1', 1, 'key2', 2, 'key3', 3.5)
IDL> r = hs1 EQ hs2
IDL> HELP, r
R               LIST  <ID=30  NELEMENTS=2>
IDL> PRINT, r
key1
key2

 

< 해쉬 개체와 단일값 사이의 비교 >

 

해쉬 개체와 단일값을 비교하는 경우에는 다음 예제와 같이 해쉬 개체 내에서 값(Value)이 비교 대상인 단일값과 일치하는 항목들에 대한 키 값들을 얻을 수 있습니다. 만약 EQ 대신 NE 연산자를 사용할 경우에는 EQ를 적용할 경우와 정반대의 결과를 얻게 됩니다.

 

IDL> hs = HASH('key1', 1.414, 'key2', 3.14, 'key3', 1.414, 'key4', 1.415)
IDL> r = hs EQ 1.414
IDL> HELP, r
R               LIST  <ID=36  NELEMENTS=2>
IDL> PRINT, r
key1
key3

 

이상과 같이 해쉬(Hash) 자료형의 주요 특성들을 살펴보았습니다. 여기서 다루지 못한 더 많은 관련 내용들은 IDL 도움말에서 HASH 함수에 관한 섹션을 참조하시면 됩니다.

 

 

* 이 내용은 지난 2011년에 올렸던 게시물의 내용을 일부 수정하여 다시 새롭게 올리는 내용입니다. 따라서 기존의 게시물은 이번 내용으로 대체되었습니다.

 

* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.

 

LIST

'IDL > Data Type & Format' 카테고리의 다른 글

구조체(Structure)에 관하여  (1) 2025.06.24
리스트(List) 자료형에 관하여 [2]  (2) 2025.06.05
리스트(List) 자료형에 관하여 [1]  (0) 2025.06.04
ISA 함수의 활용  (0) 2025.06.02
TYPENAME 함수의 활용  (0) 2025.05.29