在TCL SCRIPT中,如何添加字典或数组

在TCL SCRIPT中,如何添加字典或数组

我正在尝试创建一个输出格式关键字 起始号码 结束号码字典或数组格式。在我的代码中,我使用了字典,代码如下:

set keyword_numbers {}
set previous_keyword ""
set last_no 0
foreach item $data {

    regexp {(\w+)\[(\d+)\]} $item -> keyword number
    set new_keyword "$keyword $number"
    puts $keyword
    set key_start_end_data [dict create ]
    if {$keyword == $previous_keyword} {
        if { $number > $last_no } {
            set last_no $number
        } else {
            set last_no $number
        }
        dict lappend key_start_end_data $keyword_data bit_end $last_no
        
    } else {
        set new_keyword $keyword
        set start_no $number
        set keyword_data [lindex $new_keyword 1]
        dict lappend key_start_end_data $keyword_data bit_start $start_no
    }

puts $key_start_end_data
set previous_keyword $keyword
}

输入在哪里,或者 $data 包含

BITS_CLK2QDLY[0]
BITS_CLK2QDLY[1]
BITS_DCC_MAIN[0]
BITS_DCC_MAIN[1]
BITS_DCC_MAIN[2]
BITS_DCC_MAIN[3]
BITS_DCC_MAIN[4]
BITS_DCC_MAIN[5]
BITS_DCC_MAIN[6]
BITS_FIXDLY_MAIN[0]
BITS_FIXDLY_MAIN[1]
BITS_FIXDLY_MAIN[2]
BITS_FIXDLY_MAIN[3]
BITS_FIXDLY_MAIN[4]
BITS_FIXDLY_MAIN[5]
BITS_FIXDLY_MAIN[6]
BITS_FIXDLY_MAIN[7]
BITS_NDE_DLY[0]
BITS_NDE_DLY[1]
BITS_NDE_DLY[2]
BITS_NDE_DLY[3]
BITS_NDE_DLY[4]
BITS_NDE_DLY[5]
BITS_NDE_DLY[6]
BITS_NDE_DLY[7]

预期输出在字典中

BITS_DCC_MAIN { bit_end: 0 bit_start: 6 }
BITS_FIXDLY_MAIN { bit_end: 0 bit_start: 7 }
BITS_NDE_DLY{ bit_end: 0 bit_start: 7 }

或数组

BITS_CLK2QDLY [ 0 1 ]
BITS_DCC_MAIN [ 0 6 ]
BITS_FIXDLY_MAIN [0 7 ]
BITS_NDE_DLY[ 0 7 ]

这就是我得到的

{} {bit_start 0}
{} {bit_end 1}
{} {bit_start 0}
{} {bit_end 1}
{} {bit_end 2}
{} {bit_end 3}
{} {bit_end 4}
{} {bit_end 5}
{} {bit_end 6}
{} {bit_start 0}
{} {bit_end 1}
{} {bit_end 2}
{} {bit_end 3}
{} {bit_end 4}
{} {bit_end 5}
{} {bit_end 6}
{} {bit_end 7}
{} {bit_start 0}
{} {bit_end 1}
{} {bit_end 2}
{} {bit_end 3}
{} {bit_end 4}
{} {bit_end 5}
{} {bit_end 6}
{} {bit_end 7}

有人能告诉我这段代码有什么问题吗?请在评论部分中提及与我的问题或澄清相关的任何疑问。

答案1

与@Nikita 的方法类似,仅供比较。如果数字可能无序,Nikita 的方法更好。

set keyword_numbers {}
foreach item $data {
    if {[regexp {(\w+)\[(\d+)\]} $item -> keyword number]} {
        if {![dict exists $keyword_numbers $keyword]} {
            dict set keyword_numbers $keyword bit_start $number
        }
        dict set keyword_numbers $keyword bit_end $number
    }
}
puts [list $keyword_numbers]
{BITS_CLK2QDLY {bit_start 0 bit_end 1} BITS_DCC_MAIN {bit_start 0 bit_end 6} BITS_FIXDLY_MAIN {bit_start 0 bit_end 7} BITS_NDE_DLY {bit_start 0 bit_end 7}}

答案2

第一个问题是,你为输入的每一行打印一行输出。而据我理解,你的输出不会逐行匹配输入。所以,至少最后一个puts是错误的;它可能对调试有用,但对最终结果的输出没有用。

其次,您将每个循环迭代重新设置key_start_end_data为一个空字典。可能您只想在循环之前或切换到新关键字时执行此操作?此外,在重置之前,您必须将其结果值复制到某个非易失性变量中,但您没有将其用于keyword_numbers任何事情。它是否旨在收集结果数据?

第三,这是错误的用法dict lappend。它旨在将某个字典项的值附加到列表中;你没有这样的结构,它对这个问题没有用。你可能想使用dict set替换给定键的字典值,或者创建键并将其设置为值(如果不存在):

dict set key_start_end_data bit_start $number

最后,虽然您的代码可以调试,但它太冗长且变量太多,因此很难阅读和理解。将其与以下内容进行比较:

set keyword_numbers {}

foreach item $data {
    if {[regexp {(\w+)\[(\d+)\]} $item -> keyword number]} {
        if [dict exists $keyword_numbers $keyword] {
            dict set keyword_numbers $keyword bit_start \
                [expr {min([dict get $keyword_numbers $keyword bit_start], $number)}]
            dict set keyword_numbers $keyword bit_end \
                [expr {max([dict get $keyword_numbers $keyword bit_end], $number)}]
        } else {
            dict set keyword_numbers $keyword \
                [dict create bit_start $number bit_end $number]
        }
    }
}

puts $keyword_numbers

if {[regexp ...]}使其仅处理与正则表达式匹配的行。这只是一个保障。然后,如果这个关键字之前已经出现过,它会将其 bit_start 和 bit_end 替换为当前行应该替换的内容;如果关键字是新的,它会重新创建它,并将两个子元素设置为当前行中的数字。此代码将成功处理更为宽松的输入,例如,您可以打乱输入的行,结果仍然相同。我换行了长行;这不是必要的,但在这里看起来更好。

我没有将输出处理为输出行。为此,puts您可以执行以下操作,而不是使用 last single :

dict for {key val} $keyword_numbers {
    puts "$key {$val}"
}

它将值放入 TCL 的字典格式中,不带冒号

相关内容