遍历多个TCL数组
我想循环一个或多个TCL数组,例如打印一个特定的值 也许最好用代码来描述:遍历多个TCL数组,tcl,Tcl,我想循环一个或多个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 ma
# 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)"
}
那个“有效”的案例产生了一个副本(我想这没什么大不了的),但它看起来并不正确。我更喜欢一些更干净的东西,比如“不”的箱子(但它是有效的:)。我同意这很难看。最好的方法是使用局部变量别名。您可以使用
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
,以避免一些难看的错误解析问题。)我同意这是难看的。最好的方法是使用局部变量别名。您可以使用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
,请始终使用上面的level参数-0
和1
,以避免一些难看的错误解析问题。)如果您真的想让Nope案例起作用,另一种解决方案是记住$x
只是[set x]的简写
和set
,作为一个合适的命令,它比仅仅是语法的$
更好地使用了tcl语法的其余部分
因此,将您的双精度$$
重新格式化为集合
将为我们提供以下工作代码:
foreach ar "one two" {puts [set [set ar](param)]}
第一轮替换,
[set ar]
仅将ar
替换为值“一”或“二”。在这种情况下,set
比$
的优势在于,它让程序员能够控制在何处停止替换。我们可以做与$ar(param)
相同的[set ar(param)]
,或者我们可以更早地停止:[set ar](param)
,这就是我们在这种情况下想要的。如果你真的想让Nope案例起作用,另一种解决方案是记住$x
只是[set x]的简写
和set
,作为一个合适的命令,它比仅仅是语法的$
更好地使用了tcl语法的其余部分
因此,将您的双精度$$
重新格式化为集合
将为我们提供以下工作代码:
foreach ar "one two" {puts [set [set ar](param)]}
第一轮替换,
[set ar]
仅将ar
替换为值“一”或“二”。在这种情况下,set
比$
的优势在于,它让程序员能够控制在何处停止替换。我们可以执行与$ar(param)
相同的[set ar(param)]
,也可以提前停止:[set ar](param)
,这是我们在这种情况下需要的。或者,您可以更改数据结构:
# 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)}
或者,您可以更改数据结构:
# 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)}
实际上,第二个
集合
是不必要的。您可以像这样编写foreach ar“一两”{put“$ar=[set${ar}(param)]”}
$foo
不是set foo
的缩写。请参见trace
@JohannesKuhn:“$foo是[set foo]的缩写”这句话是用来解释tcl替代规则的传统说法。此外,为了trace
的目的,$foo
和set foo
都触发变量跟踪(虽然显然只有set foo
会触发set
上的命令跟踪),实际上,第二个set
是不必要的。您可以像这样编写foreach ar“一两”{put“$ar=[set${ar}(param)]”}
$foo
不是set foo
的缩写。请参见trace
@JohannesKuhn:“$foo是[set foo]的缩写”这句话是用来解释tcl替代规则的传统说法。此外,为了<代码> Trace<代码> < <代码> $Fo< <代码>和>代码> SET FoO 触发器变量跟踪(虽然显然仅<代码> SET FoO 将触发命令跟踪在<代码> SET>代码>),我考虑DAONE研究员glenn jackman提供的所有答案,斯莱贝特曼要准确地回答我要做的事情的意图。我选择了@ SkyBeman,因为它最接近回答我的具体问题:我如何写“NoPE”的案例?我认为DANOL研究员、glenn jackman和SybBeman提供的所有答案都是正确的,并且正确地回答了我试图做的事情的意图。我之所以选择@slebetman,是因为它最接近于回答我的具体问题:我如何编写“否”案例?