我想循环遍历一个或多个TCL数组,例如打印特定值。
也许最好在代码中描述:
# Init
array unset one; array set one {param 1}
array unset two; array set two {param 2}
#Works fine
puts "one=$one(param)"
puts "two=$two(param)"
#Nope
foreach ar "one two" {puts ${$ar(param)}}
#Works, but makes a copy.
foreach tmp "one two" {
array unset ar
array set ar [array get $tmp]
puts "$tmp=$ar(param)"
}
那"作品"案例导致副本(我认为这没什么大不了的),但它看起来并不正确。我更喜欢有一些更干净的东西,例如" Nope"案例(但有效:)。
答案 0 :(得分:2)
我同意这很难看。执行此类操作的最佳方法是使用局部变量别名。你制作upvar 0
。
foreach arrayName {one two} {
upvar 0 $arrayName ar
puts "$arrayName=$ar(param)"
}
您建议这最好在一个过程中完成,因为您无法真正撤消变量别名。这可以使upvar
的使用更加传统。
proc printEntry {entry args} {
foreach arrayName $args {
# Use [upvar 1] because we want the caller's name
upvar 1 $arrayName ar
puts "$arrayName=$ar($entry)"
}
}
printEntry param one two
(如果您使用的是upvar
,请始终使用上面的级别参数 - 0
和1
- 以避免一些难看的错误解析问题。)
答案 1 :(得分:1)
备用解决方案,如果您确实希望Nope案例有效,请记住$x
只是[set x]
和set
的简写,作为一个正确的命令,使用tcl语法的其余部分比仅仅是语法的$
更好。
因此,将您的双$$
重新制定为set
会为我们提供此代码:
foreach ar "one two" {puts [set [set ar](param)]}
第一轮替换,[set ar]
仅用{"一个"替换ar
。或者"两个"。在这种情况下set
优于$
的优势在于它使程序员能够控制在何处停止替换。我们可以[set ar(param)]
与$ar(param)
相同,或者我们可以提前停止:[set ar](param)
这就是我们在这种情况下想要的。
答案 2 :(得分:1)
或者,您可以更改数据结构:
# Init
array set a {
"one,param" 1
"two,param" 2
}
puts "one=$a(one,param)"
puts "two=$a(two,param)"
foreach key {one two} {puts $a($key,param)}