我目前正在使用循环将值迭代到Tcl中的进程(邻居)中。
for {set i 0} {$i < $val(nn)} {incr i} {
for {set j 0} {$j < $val(nn)} {incr j} {
$ns at 0.0 "neighbors $node($i) $node($j) $i $j"
}
}
以上内容允许我进入流程所需的所有值。但是,在过程内部,某些值已分配(到列表中),不再需要遍历。流程中的简短摘要:
} else {
puts "..... Do nothing .... $nd1 - $nd2"
if {([lsearch -exact $heads $nd1] != -1) || ([lsearch -exact $members $nd1] != -1) } {
incr $nd1
}
}
这是过程循环的结尾。 puts
只是一个标记,但是它检查项目是否包含在两个两个列表中的任何一个中。如果它在任何一个列表中,则将其递增,然后继续下一个可能的值。该值不再需要检查/循环,因为它已被放入列表中。
如何防止该值继续使用? “过程调用”循环将始终覆盖过程中发生的情况,因此即使分配的值也将继续使用。有没有其他方法可以在Tcl中调用进程?或者至少是将值馈送到Tcl中的过程的另一种方式?还是我猜出来了?
请注意,这是我要提供给我的进程(n1和n2是内存位置,nd1 nd2是实际数字标识符)
set heads {}
set members {}
proc neighbors {n1 n2 nd1 nd2} {
global heads members bool allNodes
puts "Members --- $members"
puts "heads --- $heads"
if {([lsearch -exact $heads $nd1] == -1) && ([lsearch -exact $members $nd1] == -1) } {
lappend heads $nd1
set currentHead $n1
puts "Current Head: $currentHead $n1 $nd1"
} else {
puts "..... Do nothing .... $nd1 - $nd2"
if {$nd1 in $heads || $nd1 in $members} then return
#here I want it to go to the next nd1 value and NEVER use it again if it
#has already been processed
}
#Otherwise, do neighbor test with nd2
答案 0 :(得分:1)
如果neighbors
操作为symmetric(通常为true),则按照以下所有内容检查所有内容:
for {set i 0} {$i < $val(nn)} {incr i} {
for {set j $i} {$j < $val(nn)} {incr j} {
$ns at 0.0 [list neighbors $node($i) $node($j) $i $j]
}
}
,内部循环从$i
开始(如果不想对自己进行检查,则从[expr {$i - 1}]
开始)而不是零。这样可以确保$j
始终不小于$i
,从而有效地(大约)将您需要做的工作量减半。
(样式要点:使用[list ...]
来准备代码供以后执行,而不是"..."
被认为是很好的样式;前者效率更高 后者情况有些丑陋当使用可能有空格的值时。)
您不能做的事(至少不容易;至少有一种方法可以做到)是使用neighbors
操作的结果来阻止将来对neighbors
的调用发生,因为您已经安排它们在它们中的任何一个都可以发表意见时出现。在您的情况下,保留状态变量并对其进行检查以选择是否可以进行早期拒绝可能更容易。这是使用延迟的命令调用而不是直接的命令的根本限制:将值传递回去做诸如跳过将来的迭代之类的操作是非常困难的(在Tcl 8.6之前是非常棘手的; coroutine
大大简化了任务)。 / p>
答案 1 :(得分:0)
感觉就像您想这样做:
proc neighbors {n1 n2 nd1 nd2} {
global heads members bool allNodes
if {$nd1 in $heads || $nd2 in $members} then return
... do the neighborly stuff ...
}
有关in
运算符,请参见https://tcl.tk/man/tcl8.6/TclCmd/expr.htm#M15。