2009-08-24 461 views
4

如何创建并通过TCL哈希的遍历一个哈希表?如何在TCL中创建并遍历散列哈希值?

如果我有这样的数据:

foo = { 
    a => { 
     aa => { aa1 aa2 aa3 } 
     ab => { ab1 ab2 ab3 } 
     ac => { ac1 ac2 ac3 } 
    } 
    b => { 
     ba => { ba1 ba2 ba3 } 
     bb => { bb1 bb2 bb3 } 
     bc => { bc1 bc2 bc3 } 
    } 
    c => { 
     ca => { ca1 ca2 ca3 } 
     cb => { cb1 cb2 cb3 } 
     cc => { cc1 cc2 cc3 } 
    } 
} 

如何创建通过一次插入一个叶子节点的数据项这样的哈希值。喜欢的东西:

lappend富(一)(AB) “AB1”

那我怎么遍历所有数据元素?像:

foreach key in foo { 
    foreach sub_key in foo($key) { 
     foreach elem in foo($key)($sub_key) { 
      puts "foo\($key\)\($sub_key\) is $elem" 
     } 
    } 
} 

编辑: 不幸的是,我没有进入到较新的“字典”建设。

+0

我分开我的答案突出非字典解决方案。 – 2009-08-24 20:43:26

回答

7

如果你不使用Tcl 8.5,那么你可以使用数组。需要注意的是阵列是一维的,但关键是,可用于假多维度的任意字符串:

array set foo {} 
foreach first {a b c} { 
    foreach second {a b c} { 
     foreach third {1 2 3} { 
      lappend foo($first,$first$second) "$first$second$third" 
     } 
    } 
} 
parray data 

,并将其输出 - 注意:数组键,不像字典键,是无序:

foreach key [array names foo] { 
    foreach elem $foo($key) { 
     puts "$key\t$elem" 
    } 
} 

如果你给出的键(例如“b”和“BC”),你可以得到正是如此值:

set key1 b 
set key2 bc 
foreach elem $foo($key1,$key2) {puts $elem} 
8

假设你正在使用Tcl 8.5+,字典是要走的路:

定义词典做法仅仅是:

set foo { 
    a { 
     aa { aa1 aa2 aa3 } 
     ab { ab1 ab2 ab3 } 
     ac { ac1 ac2 ac3 } 
    } 
    b { 
     ba { ba1 ba2 ba3 } 
     bb { bb1 bb2 bb3 } 
     bc { bc1 bc2 bc3 } 
    } 
    c { 
     ca { ca1 ca2 ca3 } 
     cb { cb1 cb2 cb3 } 
     cc { cc1 cc2 cc3 } 
    } 
} 

或以编程方式进行定义:

set foo [dict create] 
foreach first {a b c} { 
    dict update foo $first subdict { 
     foreach second {a b c} { 
      foreach third {1 2 3} { 
       dict lappend subdict "$first$second" "$first$second$third" 
      } 
     } 
    } 
} 

并输出:

dict for {key1 subdict} $foo { 
    dict for {key2 list} $subdict { 
     foreach elem $list { 
      puts "$key1\t$key2\t$elem" 
     } 
    } 
} 

编辑:移动所述阵列的溶液(非字典)到单独的答案。

+0

我没有权限访问'dict'结构..谢谢你的回答。 – 2009-08-24 20:03:25

1

如果你只是想通过一个字典迭代(这是一个简单的键值对列表)w ithout的字典命令,那么可以简单地使用的foreach的迷死:

set foo { 
    a { 
    aa { aa1 aa2 aa3 } 
    ab { ab1 ab2 ab3 } 
    ac { ac1 ac2 ac3 } 
    } 
    b { 
    ba { ba1 ba2 ba3 } 
    bb { bb1 bb2 bb3 } 
    bc { bc1 bc2 bc3 } 
    } 
    c { 
    ca { ca1 ca2 ca3 } 
    cb { cb1 cb2 cb3 } 
    cc { cc1 cc2 cc3 } 
    } 
} 

foreach {key value} $foo { 
    foreach {sub_key sub_value} $value { 
    foreach elem $sub_value { 
     puts "foo\($key\)\($sub_key\) is $elem" 
    } 
    } 
} 

在另一方面,在插入元件的一个在一个时间是没有字典命令痛苦:

set foo {} 
lappend foo a {} 
set a_index [lsearch $foo a] 
set a_value_index [expr {$a_index+1}] 
set a_value [lindex $foo $a_value_index] 
lappend a_value aa {} 
lset foo $a_value_index $a_value 
# it is now too painful for me to continue :-(

好在可以使用一个纯Tcl实现字典命令:forward-compatible dict

1

如果你不具备的Tcl 8.5字典的奢华,使用键列表命令来完成这项工作。您可以通过以下其中一个条款来搜索:keylget,keylset。

package require Tclx 

# Create the nested structure 
catch {unset foo} 
foreach key1 {a b c} { 
    foreach key2 {a b c} { 
     catch {unset element} 
     foreach key3 {1 2 3} { 
      lappend element "$key1$key2$key3" 
     } 
     keylset foo $key1.$key1$key2 $element 
    } 
} 

# Access the nested structure 
foreach key1 {a b c} { 
    foreach key2 {a b c} { 
     set elementList [keylget foo $key1.$key1$key2] 
     foreach element $elementList { 
      puts "foo\\$key1\\$key1$key2\\$key3 = $element" 
     } 
    } 
} 

# 
# Access examples 
# 

# Access a block of data 
puts "foo\\a = [keylget foo a]" 
# Access a nested block of data 
puts "foo\\b\\ba = [keylget foo b.ba]" 
# Access an individual element, remember that Tcl's list index is 0 based 
puts "foo\\c\\cb\\1 = [lindex [keylget foo c.cb] 0]"