我是Tcl阵列的新手。我的问题如下。
我有一个带有两行R1和R2的矩形框。这些行中的每一行都有8个不同的值。 我想在文本文件中或作为proc的列表输出返回这16个值(x和y坐标)。我读过一些关于Tcl proc的早期帖子,除非我们使用dict,否则无法输出数组。 所以,我会尝试绘制一张图片,以便您更好地理解我的问题。
R1 x1y1 x2y2 ... x8,y8 R2 x9,y9 ... x16, y16
我在命令提示符下或在具有虚拟值的文件中运行proc时的预期输出
$> (1,2) (2,3) (3,4) ....... (7,8) (9,10) (10,11) ......... (15,16)
所以这就是我尝试过的,我得到了我需要的结果。但这是两行的硬编码。我想让它能够检测到有多少行,然后相应地输出行数。
proc getPointList {rect_boundary rowOffset colOffset rowIncr colIncr } {
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set list "" ;
for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} { incr y $colIncr } {
for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} { incr x $rowIncr } {
set list "$list $x $y" ;
puts "Value of x is: $x"; puts "\t Value of y is: $y" ;
}
}
return $list
}
set rect_boundary {10 15 100 40} # xl yl xh yh
set rowOffset 5
set colOffset 5
set rowIncr 10
set colIncr 15
我需要在此代码中基于yh-yl和xh-xl实现一些逻辑,以计算矩形的高度和宽度,并相应地输出行
调用proc
的命令$> getPointList $rect_boundary $rowOffset $colOffset $rowIncr $colIncr
为了您的理解,在特定行的矩形内有八个x,y点。 x offset是从左边或roght边界开始的一行中的第一个x点,此后所有的点都用增量值分隔,我称之为rowIncr。同样适用于列。
预期输出:这是上面的代码所做的,但它是两行的硬编码。如果行和列是可变的,我想增加并实现逻辑。
$> R1: (15 40) (25 40) (35 40) (45 40) (55 40) (65 40) (75 40) (85 40) (95 40)
R2: (15 15) (25 15) (35 15) (45 15) (55 15) (65 15) (75 15) (85 15) (95 15)
矩形图像为了更清晰,因为这件事不会让我更新图片
__________________________________________________________________________ (100,40)
| |- 5 |
| . . . . . . . . |
| |- 15 |
|-5-. . --10---. . . . . . |
| |
|_________________________________________________________________________|
(10,15)
杰里:
Case1 rowIncr 10 colIncr 20
__________________________________________________________________________ (80,40)
| |- 5 |
| . . . . . . . . |
| |- 20 |
|-5-. . --10---. . . . . . |
| |
|_________________________________________________________________________|
(10,10)
Case2 rowIncr 20 colIncr 35
_________________________________________________ (100,70)
| |- 5 |
| . . . . . |
| |- 35 |
|-5-. . --20---. . . |
| | |-5 |
|________________________________________________|
(10,25)
依旧......
答案 0 :(得分:1)
好吧,我想我现在明白你要做什么了,我认为你的proc会在一些修复之后适用于任意行:
set output [open "output.txt" w]
proc getPointList {rect_boundary rowOffset colOffset plist} {
global output
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set xpoints [llength [lindex $plist 0]]
set ypoints [llength $plist]
set rowIncr [expr {($xh-$xl-2*$rowOffset)/($xpoints-1)}]
set colIncr [expr {($yh-$yl-2*$colOffset)/($ypoints-1)}]
set count 0
set list ""
for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} {incr y -$colIncr} {
for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} {incr x $rowIncr} {
lappend list "($x,$y)"
}
incr count
puts $output "R$count: [join $list " "]"
set list ""
}
}
set plist {{A B C D E} {A B C D E} {A B C D E} {A B C D E} {A B C D E}}
set rect_boundary {0 0 100 100}
set rowOffset 0
set colOffset 0
getPointList $rect_boundary $rowOffset $colOffset $plist
close $output
我更改了colIncr
以添加更多行。
在第一个循环中,我使用了incr y -$colIncr
,因为如果你从较高的y
坐标开始,这实际上是一个减量。
我还更改了输出结构以匹配您要查找的输出结构。上面的代码片段返回坐标:
R1: (0,100) (25,100) (50,100) (75,100) (100,100)
R2: (0,75) (25,75) (50,75) (75,75) (100,75)
R3: (0,50) (25,50) (50,50) (75,50) (100,50)
R4: (0,25) (25,25) (50,25) (75,25) (100,25)
R5: (0,0) (25,0) (50,0) (75,0) (100,0)
编辑:添加了变量偏移,每行空行最后一行和变量列。
proc getPointList {rect_boundary uRowOffset lRowOffset uColOffset lColOffset plist} {
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set xpoints 0
foreach r $plist {
if {[llength $r] > $xpoints} {set xpoints [llength $r]}
}
set ypoints [llength $plist]
set rowIncr [expr {($xh-$xl-$lRowOffset-$uRowOffset)/($xpoints-1)}]
set colIncr [expr {($yh-$yl-$lColOffset-$uColOffset)/$ypoints}]
set count 0
set list ""
for {set y [expr {$yh - $uColOffset}]} {$y >= [expr {$yl + $lColOffset}]} {incr y -$colIncr} {
set x [expr {$xl + $lRowOffset}]
foreach n [lindex $plist $count] {
lappend list $x $y
incr x $rowIncr
}
incr count
if {$count == $ypoints} {return $list}
}
}
set plist {{A B C D X} {E F G H} {I K L} {M N}}
set qlist 1
foreach n $plist {
set pattern$plist $n
incr qlist
}
set rect_boundary {0 0 100 100}
set upperRowOffset 0
set lowerRowOffset 0
set upperColOffset 0
set lowerColOffset 0
set pointList [getPointList $rect_boundary $upperRowOffset $lowerRowOffset $upperColOffset $lowerColOffset $plist]
set count 1
foreach sub_list $plist {
foreach n $sub_list {
set pattern$count $n
incr count
}
}
set count 1
foreach {a b} $pointList {
set text "pattern$count"
puts "command -point $a,$b -text [set $text]"
incr count
}
答案 1 :(得分:0)
由您决定如何组织嵌套列表。最简单的形式,返回一个列表:
set result {x1 y1 x2 y2 ... x16 y16}
或者,您可以列出两行:
set result {
{x1 y1 x2 y2 ... x8 y8}
{x9 y9 x10 y10 ... x16 y16}
}
或者,更复杂:每对都是一个子列表:
set result {
{ {x1 y1} {x2 y2} ... }
{ {x9 y9} {x10 y10} ... }
}
在这种情况下,我认为你不想使用数组。仅供参考,TCL中的“数组”相当于其他语言中的 hash 。
答案 2 :(得分:0)
好吧,使用Tcl 8.6
proc parsedata {input} {
lmap a [split $input \n] {
lmap b [split $b \t] {
regexp {x(\d+),?\s*y(\d+)} $b -> c d
list $c $d
}
}
}
现在您可以处理数据,例如:
foreach line [parsedata $input] {
puts [lmap pair $line {
expr {"([lindex $line 0],[linedex $line 1])"}
}
}