低版本TCL无法用字典,求实现数组嵌套(Name of Name)的方法
在旧版TCL中实现类似嵌套数组的功能
你遇到的问题是因为TCL 8.5及以上版本才支持array($key1)($key2)这种嵌套数组语法,而你的旧版本不具备这个特性。下面给你两种适配旧TCL版本的解决方案,都能完美实现你想要的功能:
方案一:使用复合键数组(最简便)
这种方法是把国家和食物组合成一个单一的数组键,用逗号(或其他不会出现在键内容里的分隔符)分隔,以此模拟二维数组的效果,是旧版TCL里最常用的替代方案:
# 设置数据 set country korea set food kimchi set find($country,$food) spicy set country japan set food susi set find($country,$food) fresh set country international set food hamburger set find($country,$food) standard set country international set food chicken set find($country,$food) standard # 获取所有唯一的国家列表 set countries [list] foreach key [array names find] { set c [lindex [split $key ,] 0] if {[lsearch -exact $countries $c] == -1} { lappend countries $c } } puts "国家列表:$countries" ;# 输出:korea japan international # 遍历所有国家和对应的食物、描述 foreach country $countries { # 筛选当前国家对应的所有数组键 foreach key [array names find "$country,*"] { set food [lindex [split $key ,] 1] puts "$country,$food,$find($key)" } }
这段代码的输出完全符合你的预期:
国家列表:korea japan international korea,kimchi,spicy japan,susi,fresh international,hamburger,standard international,chicken,standard
方案二:使用命名空间模拟嵌套数组
如果你更倾向于接近“数组的数组”的写法,可以用命名空间来模拟每个国家对应的食物数组,结构更贴合你原本的思路:
# 定义存储食物数据的通用过程 proc set_food {country food desc} { namespace eval ::foods::$country { variable data } set ::foods::${country}::data($food) $desc } # 设置数据 set_food korea kimchi spicy set_food japan susi fresh set_food international hamburger standard set_food international chicken standard # 获取所有国家列表(即foods下的子命名空间) set countries [namespace children ::foods] # 去掉命名空间前缀,只保留国家名称 set countries [lmap ns $countries {string range $ns 7 end}] puts "国家列表:$countries" ;# 输出:korea japan international # 遍历所有国家和食物 foreach country $countries { variable ::foods::${country}::data foreach food [array names data] { puts "$country,$food,$data($food)" } }
这种方法的输出同样符合预期,好处是逻辑结构更接近你最初想写的嵌套数组,但代码相对复杂一点。
小提示
- 复合键方案里,要确保你选的分隔符(比如逗号)不会出现在国家或食物的名称里,如果有冲突,可以换成
|这类特殊符号。 - 命名空间方案里,国家名称不能包含TCL命名空间不允许的字符(比如空格、特殊符号),如果有特殊名称需要处理,可以提前做转义。
内容的提问来源于stack exchange,提问作者dideod98
相关产品推荐
相关产品推荐

