Tcl proc输出列表或数组

时间:2013-08-19 20:53:41

标签: arrays list tcl proc

我是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)

依旧......

3 个答案:

答案 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])"}
    }
}