Tcl 如何使proc更有效?
有一组顶点:[x1 y1 x2 y2..xn yn] 我想改变这些坐标的中心。所以我试着:Tcl 如何使proc更有效?,tcl,polygon,Tcl,Polygon,有一组顶点:[x1 y1 x2 y2..xn yn] 我想改变这些坐标的中心。所以我试着: proc changeCenter { vertices X Y } { set myList [list] foreach element $vertices { lappend myList [expr [lindex $element 0] + $X] lappend myList [expr [lindex $element 1] + $Y]
proc changeCenter { vertices X Y } {
set myList [list]
foreach element $vertices {
lappend myList [expr [lindex $element 0] + $X]
lappend myList [expr [lindex $element 1] + $Y]
}
return $myList
}
但是它的性能太慢了
如何更改上述代码以提高效率,或者可能需要更改顶点的表示形式?最简单的方法是通过支撑表达式:
proc changeCenter { vertices X Y } {
set myList [list]
foreach {x0 y0} $vertices {
lappend myList [expr {$x0 + $X}]
lappend myList [expr {$y0 + $Y}]
}
return $myList
}
这有几个好处:
- 这些数字不必转换成字符串并返回
- 表达式可以编译
- 您不会遇到字符串表示引入的严重舍入错误
- 它防止注入您不想执行的代码
如果不使用嵌套列表作为输入,请将foreach与多个变量一起使用。您的changeCenter程序指示顶点集合是一个对列表(
{{x1 y1}{x2 y2}…}
),但您返回的是一个平面列表:
proc changeCenter { vertices deltaX deltaY } {
set recentered [list]
foreach vertex $vertices {
lassign $vertex x y
lappend recentered [list [expr {$x + $deltaX}] [expr {$y + $deltaY}]]
}
return $recentered
}
如果顶点确实是一个平面列表({x1 y1 x2 y2…}
),则一次读取列表中的2个元素:
proc changeCenter { vertices deltaX deltaY } {
set recentered [list]
foreach {x y} $vertices {
lappend recentered [expr {$x + $deltaX}] [expr {$y + $deltaY}]
}
return $recentered
}
我还没有对其进行基准测试,但我怀疑在适当的位置更新顶点列表可能比附加到新列表更快:
proc changeCenter { vertices deltaX deltaY } {
for {set i 0} {$i < [llength $vertices]} {incr i} {
lset vertices $i 0 [expr {[lindex $vertices $i 0] + $deltaX}]
lset vertices $i 1 [expr {[lindex $vertices $i 1] + $deltaY}]
}
return $vertices
}
proc changeCenter { vertices deltaX deltaY } {
for {set i 0} {$i < [llength $vertices]} {incr i 2} {
lset vertices $i [expr {[lindex $vertices $i] + $deltaX}]
set j [expr {$i + 1}]
lset vertices $j [expr {[lindex $vertices $j] + $deltaY}]
}
return $vertices
}
proc changeCenter { verticesName deltaX deltaY } {
upvar 1 $verticesName v
for {set i 0} {$i < [llength $v]} {incr i 2} {
lset v $i [expr {[lindex $v $i] + $deltaX}]
set j [expr {$i + 1}]
lset v $j [expr {[lindex $v $j] + $deltaY}]
}
# no need to return a value
}
changeCenter vertices 1 2