IDL/Data Type & Format

새로운 Data Type인 해쉬(Hash)에 관하여

이상우_idl 2011. 5. 16. 07:01
728x90
반응형

IDL 8.0부터 새롭게 도입된 자료형(Data Type)인 리스트(list)와 해쉬(hash)에 관하여 순차적으로 소개하고 있습니다. 오늘은 두번째 순서로 해쉬(hash)에 관하여 알아보기로 하겠습니다. 이 해쉬(hash)라는 자료형은 일종의 복합적인 성격을 띄고 있다는 측면에서, 앞서 소개된 리스트(list)나 구조체(structure)와 유사한 면이 있습니다. 하지만 해쉬는 일종의 사전(Dictionary)와 같은 성격을 띕니다. 즉, 어떤 원소값이 있으면 이를 지정하는 키(key)라는 것이 존재하여, 키-원소값의 쌍(key-value pair)의 형태로 구성됩니다. 이러한 '사전'과 같은 개념은 이미 다른 프로그래밍 언어들에서도 차용하고 있는 개념인 것으로 압니다. 먼저 해쉬의 전반적인 특성들을 살펴보면 다음과 같습니다.

 

1. 해쉬의 원소들은 순서에 따른 정렬이라는 개념이 없고, 키(key)를 통해서만 그 원소값에 접근할 수 있다.

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

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

 

아마 1번을 제외하면 리스트와 매우 유사하다는 점을 발견할 수 있습니다. 해쉬를 생성하려면 HASH라는 함수를 사용합니다. 해쉬내의 원소들은 어떤 자료형이든 가능하며, 단일값 또는 배열이든 상관이 없습니다. 심지어 구조체나 포인터도 원소가 될 수 있습니다. 다음은 원소의 갯수가 3인 해쉬를 임의로 간단하게 생성해본 것입니다.

 

IDL> my_hash = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> PRINT, N_ELEMENTS(my_hash)

3

IDL> PRINT, my_hash['red']

255  0  0

 

여기서는 해쉬를 생성할 때 HASH 함수를 사용하되 이 안에 들어가는 인자들은 (키1,원소값1, 키2, 원소값2, 키3, 원소값3)과 같은 순서로 들어가 있습니다. 참고로 키는 문자나 숫자면 됩니다. 해쉬의 원소값들중 원하는 값을 가져오려면 해당 키값을 마치 인덱스와 같은 느낌으로 사용하면 됩니다. 따라서 첫번째 원소인 1.0이란 값을 끄집어내려면 my_hash['one']이 됩니다. 따라서 여기서는 원소값들 사이의 '순서'라는 개념은 없습니다. 배열이나 리스트에서 원소들의 순서에 해당되는 인덱스로 원소값을 추출하였던 것과는 전혀 다른 개념입니다. 따라서 어떤 프로그램을 만들 때, 그 프로그램안에서 자주 사용될만한 값들을 각각 나름의 이름으로 정의해놓는 유용한 방법이 될 수 있습니다. 결국 키값이라는 것은 일종의 '인식표'와 같은 역할을 하는 것입니다.

 

해쉬를 생성할 때 키와 원소값들을 각각 배열로 구성하여 HASH 함수의 인자로 사용할 수도 있습니다. 즉, 다음과 같이 정의해도 마찬가지입니다.

 

IDL> keys = ['one', 'red', 'Pi']

IDL> values = LIST(1.0, [255, 0, 0], !DPI)

IDL> my_hash = HASH(keys, values)

 

참고로 키를 문자값으로 할 경우 대소문자의 구분이 존재합니다. 위에서 정의한 my_hash에서 세번째 원소를 보면 키값이 'Pi'라는 문자로 되어 있습니다. 그런데 이 키에 해당되는 값을 가져오기 위하여 my_hash['pi']와 같이 쓰면, 그 키가 존재하지 않는다는 메시지가 뜨면서 에러가 납니다. 따라서 대소문자의 구분이 있다는 점을 유의해야 합니다. 다음은 키값으로 숫자 및 문자가 혼용된 경우입니다.

 

IDL> my_hash = HASH(13, 'Ji-Sung', 'Rooney', 9)

IDL> PRINT, my_hash[13]

Ji-Sung

IDL> PRINT, 'my_hash['Rooney']

9

 

해쉬도 리스트의 경우와 마찬가지로 몇몇 메서드들이 정의되어 있습니다. 먼저 특정한 키값이 해쉬안에 존재하는가를 판단해주는 HasKey라는 메서드가 있습니다. 존재할 경우는 1, 존재하지 않는다면 0이란 값을 돌려줍니다. 위에 정의된 my_hash에 대하여 적용해본 예제는 다음과 같습니다.

 

IDL> PRINT, my_hash.HasKey('Rooney')

1

IDL> PRINT, my_hash.HasKey('Ji-Sung')

0

IDL> PRINT, my_hash.HasKey([11, 3, 13])

0  0  1

 

Keys라는 메서드는 해쉬에 존재하는 모든 키값들을 리스트의 형태로 돌려줍니다.

 

IDL> keys = my_hash.Keys()

IDL> HELP, keys

<expression>  LIST  <ID=39  NELEMENTS=2>

IDL> PRINT, keys

13

Rooney

 

Remove라는 메서드는 해쉬안의 특정 원소값(또는 원소값들)을 제거하는 역할을 합니다. 그리고 제거된 원소값 또는 원소값들을 추출할 수도 있습니다. 물론 메서드의 인자는 키값이어야 합니다. 다음 예제를 봅시다.

 

IDL> my_hash = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> my_hash.Remove, 'one'

IDL> PRINT, my_hash

red:  255  0  0

Pi:  3.141597

 

IDL> my_hash = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> my_hash.Remove, ['one', 'Pi']

IDL> PRINT, my_hash

red:  255  0  0

 

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

 

IDL> my_hash = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> values = my_hash.Values()

IDL> HELP, values

<expression>  LIST  <ID=119  NELEMENTS=3>

 

두 개의 독립적인 해쉬들을 서로 합치면 구성원소들이 모두 망라된 새로운 해쉬가 됩니다.

 

IDL> hash1 = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> hash2 = HASH(13, 'Ji-Sung', 'Rooney', 9)

IDL> hash3 = hash1 + hash2

 

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

 

IDL> hash1 = HASH('one', 1.0, 'red', [255, 0, 0], 'Pi', !DPI)

IDL> struct = {Player:'Ji-Sung', Number:13}

IDL> hash3 = hash1 + struct

IDL> PRINT, hash3

one:  1.00000

red:  255  0  0

Pi:  3.141597

PLAYER:  Ji-Sung

NUMBER:  13

 

EQ 오퍼레이터를 사용하여 해쉬와 해쉬간의 또는 해쉬와 특정값과의 비교도 가능합니다. 만약 해쉬와 해쉬끼리 비교하는 경우라면, 다음 예제와 같이 두 해쉬에 모두 존재하면서 키값도 서로 같고 원소값도 서로 같은 항목들에 대한 키값들을 돌려줍니다.

 

IDL> hash1 = HASH('key1', 1, 'key2', 2, 'key3', 3, 'anotherkey', 3.14)

IDL> hash2 = HASH('key1', 1, 'key2', 2, 'key3', 3.5)

IDL> result = hash1 EQ hash2

IDL> HELP, result

RESULT    LIST  <ID=212  NELEMENTS=2>

IDL> PRINT, result

key2

key1

 

만약 해쉬와 단일값을 비교하는 경우라면, 다음 예제와 같이 해쉬내에서 원소값이 그 비교대상값과 일치하는 항목들에 대한 키값들을 돌려줍니다(참고로 NE 오퍼레이터를 적용할 경우에는 EQ를 적용할 경우와 정반대의 결과를 준다고 보면 됩니다).

 

IDL> hash = HASH('key1', 1.414, 'key2', 3.14, 'key3', 1.414)

IDL> result = hash EQ 1.414

IDL> HELP, result

RESULT    LIST  <ID=221  NELEMENTS=2>

IDL> PRINT, result

key1

key3

 

이상과 같이 해쉬라는 자료형의 주요 특성들을 살펴보았습니다. IDL 도움말에서 HASH함수에 관한 내용을 보면 좀 더 자세한 내용이 있으니, 필요하신 분들은 그 내용을 참조하시면 됩니다. 전반적으로는 해쉬는 리스트와 비슷한 행동양식을 보이는 부분이 많습니다. 어쨌든 리스트와 해쉬 모두 각각의 세부 특성 및 성격이 약간씩 다른 만큼, 그 특성을 살려서 목적에 맞게 이용하면 아마 프로그래밍에 있어서 유용하게 사용될 수 있을 것으로 생각됩니다.

 

* 이 글은 idluser.org 사이트의 IDL Tips 게시판의 119번 게시물로도 보실 수 있습니다.

반응형