You are here

Tcl의 새로운 데이타 명령어 dict

admin의 아바타

http://pascal.scheffers.net/software/

Tcl8.5 부터 추가된 새로운 데이타 형인 dict 커맨드에 대해서 알아봅니다. dict는 리스트와 배열의 중간 정도라 생각할수 있습니다. dict는 리스트를 구조체 처럼 사용하거나, 배열을 proc의 리턴값으로 돌려줄수 있는 예전 버전에서의 불편한 요소들을 해소하기 위해 추가된 커맨드입니다. dict는 해쉬(hash)로 되어 있는 배열보단 빠를것 같지만, Tcl의 경우 리스트도 어느 경우 배열보다 빠른 경우가 있기 때문에, list/array/dict 3개를 비교해 보지 않으면 알수는 없을것입니다. 우선 Tcl8.5에 기본으로 추가된 dict를 테스트 해보기전에, 정식 릴리즈가 되지 않은 불안정한 상태에서 8.5 버전의 dict 대신, 8.4버전으로도 릴리즈된 비교적 안정화 버전의 dict를 대상으로 테스트 해봅니다. (8.5버전의 dict와 동일한 기능입니다.)

옵션 목록

옵션 설명
dict append varName key ?value ...? key 값의 끝에 value를 추가.
dict create ?key value ...? 새로운 dict 생성.
dict exists dictionary key ?key ...? key가 존재 하는지 검사.
dict filter dictionary filterType ... dict를 필터(filter)링 한다.
dict for {keyVar valueVar} dictionary script foreach
dict get dictionary ?key key ...? key의 값을 돌려 준다.
dict incr varName key ?increment? incr과 동일한 의미이며, key 값을 늘린다.
dict info dictionary dict의 내부 정보를 돌려 준다.
dict keys dictionary ?pattern? key의 리스트를 돌려 준다.
dict lappend varName key ?value ...? key의 값을 리스트에 추가.
dict merge ?dictionary ...? 여러개의 dict를 연결하여 돌려 준다.
dict remove dictionary ?key ...? key의 페어(pair)를 삭제한 dict를 돌려 준다.
dict replace dictionary ?key value ...? key를 value로 치환한후의 값을 돌려 준다.
dict set varName key ?key ...? value key에 value를 세트.
dict size dictionary dict의 크기를 돌려 준다.
dict update varName key varName ?key varName ...? script key를 varName에 할당(assign) 하여 코드를 실행(8.5 전용)
dict unset varName key ?key ...? key의 페어(pair)를 삭제.
dict values dictionary ?pattern? 값의 리스트를 돌려 준다.
dict with varName ?key ...? script dict의 이름 공간(namespace)에서 코드를 실행(8.5 전용)

기본적인 사용방법

package require dict
 
set d [dict create name inhak-min]

dict를 생성시에는 name키에 inhak-min과 비슷한 값으로 지정을 합니다.

package require dict
 
set d [dict create name inhak-min]
dict set d age 28
dict set d level 10

그리고 생성된 dict 변수 d에 새로운 키와 값을 지정 하는 것은 위와 같이 합니다.

네스팅(Nesting)

dict는 다른dict를 포함할수 있습니다. 이것은 array와는 다른 점입니다.

package require dict
 
set d [dict create a [dict create aa 0] b 1]
puts $d
=> a {aa 0} b 1
 
puts [dict get $d a]
=> aa 0
puts [dict get $d a aa]
=> 0

그리고 하나의 키에 대응하는 값은 단순 문자열뿐만이 아닌 리스트도 가능합니다.

package require dict
 
set d [dict create a 0 b 1]
dict set d c {}
dict set d c cc 2
 
puts [dict get $d c]
=> cc 2

혹은

dict set d c cc 2

부분을 다음과 같이 고칠수도 있습니다.

dict set d c [list cc 2]

편리한 기능

array는 프로시져의 리턴값으로 돌려줄수 없기 때문에,

array get a

array set a

등을 사용하거나 혹은 upvar를, 또는 global 변수를 사용하여 엑세스를 해야만 합니다.

proc test {alist} {
     array set arr $alist
     ....
     return [array get arr]
}
 
array set ga {hoge 0 fuga 1}
test [array get ga]
proc test {alist} {
    upvar $alist arr
    ....
}
 
array set ga {hoge 0 fuga 1}
test ga

그러나 편리하게도 dict는 위와같이 프로시져의 리턴값으로 돌려줄수 있습니다.

package require dict
 
proc test {} {
    return [dict create hoge 0 fuga 1]
}
puts [test]

개인적인 생각은 현재의 array 기능을 제거하고, dict로 전부 통일시키는 쪽이 좋을것 같습니다. (호환성을 생각한다면 나두는것도 괜찮을것 같군요.)

filter 기능

필터는 key, value, script 와 같이 3가지 방향을 제시합니다.

  • dict filter dict key pattern
  • dict filter dict value pattern
  • dict filter dict script {keyName valueName} body
    package require dict
     
    dict filter {aa 0 ab 1 ac 2 ba 3 bb 4 bc 5} key a*
    => ac 2 aa 0 ab 1
    dict filter {n1 min n2 kim n3 park n4 byun} value mi*
    => n1 min
    dict filter {hyundai 1.15 kia 3.05 nissan -0.71} script {k v} {expr $v>0}
    => hyundai 1.15 kia 3.05
    

    update 기능 (Tcl8.5 버전만 가능)

    값의 변경

    set info {name hyundai code 7203}
    dict update info name nameVar code codeVar {
        set nameVar [string toupper $nameVar]
        set codeVar ($codeVar)
    }
    puts $info
    => name HYUNDAI code (7203)
    

    키 추가

    set info {name hyundai code 7203 price 5280}
    dict update info per perVar {
        set perVar 15
    }
    puts $info
    => name hyundai per 15 price 5280 code 7203
    

    키 삭제

    set info {name hyundai code 7203 price 5280}
    dict update info price priceVar {
        unset priceVar
    }
    puts $info
    => name hyundai code 7203
    

    body 내에서 dict에 액세스 하는 것도 가능합니다. price의 두배의 값을 price2란 키로 만들어 대입 해보겠습니다.

    set info {name hyundai code 7203 price 5280}
    dict update info price2 price2Var {
        set price2Var [expr 2 * [dict get $info price]]
    }
    puts $info
    => price2 10560 name hyundai price 5280 code 7203
    

    with 기능 (8.5 버전만 가능)

    set info {name hyundai code 7203 price 5280}
    dict with info {
        puts name=$name
        puts code=$code
        puts price=$price
    }
    => name=hyundai
    code=7203
    price=5280
    

    dict update와 같이 대응되는 키를 삭제시에는 다음과 같이 합니다.

    set info {name hyundai code 7203 price 5280}
    dict with info {
        unset name
    }
    puts $info
    => price 5280 code 7203