본문으로 바로가기

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

category 카테고리 없음 2024. 6. 17. 10:04

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