迭代几个TCL数组

时间:2014-06-11 06:22:16

标签: 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 makes a copy.
foreach tmp "one two" {
  array unset ar
  array set ar [array get $tmp]
  puts "$tmp=$ar(param)"
}

那"作品"案例导致副本(我认为这没什么大不了的),但它看起来并不正确。我更喜欢有一些更干净的东西,例如" Nope"案例(但有效:)。

3 个答案:

答案 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,请始终使用上面的级别参数 - 01 - 以避免一些难看的错误解析问题。)

答案 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)}
相关问题