如何在foreach中获取列表长度

how to get lists length within foreach

set listA "A B C"
set listB "D E"

set lists "listA listB" 
foreach l $lists { puts "$l: [llength $l]"}

它打印

listA: 1
ListB: 1 

而不是

listA: 3
listB: 2

问题是foreach循环中的$l是一个变量的name,不是一个变量的value变量。

当您有一个变量包含另一个变量的名称(而非值)时,它会产生一个重定向问题,您可以通过几种方法解决该问题。我喜欢使用 set 和一个参数来检索变量名称的值:

set listA "A B C"
set listB "D E"

set lists "listA listB" 
foreach l $lists {
    set this_list [set $l]
    puts "$l: [llength $this_list]"
}

另一种选择是将多个列表保存到关联数组中...

set my_array(listA) "A B C"
set my_array(listB) "D E"
set lists "listA listB"
foreach l $lists {
    set this_list $my_array($l)
    puts "$l: [llength $this_list]"
}

..或在字典中:

set my_dict [dict create listA "A B C" listB "D E"]
set lists [dict keys $my_dict]
foreach l $lists {
    set this_list [dict get $my_dict $l]
    puts "$l: [llength $this_list]"
}

以上所有例子中,创建变量this_list并不是必须的,只是强调获取$l.

中包含的变量名的值

另一种将字符串映射到具有该名称的变量的方法是使用堆栈级别为 0 的 upvar:

#!/usr/bin/env tclsh

set listA {A B C}
set listB {D E}

set lists {listA listB}
foreach l $lists {
    upvar 0 $l this_list
    puts "$l: [llength $this_list]"
}

(当你处理一个 proc 时会更有用,该 proc 希望在其调用者的范围内使用一个按名称传递的变量,但如果需要它也可以在相同的堆栈级别工作)