Score:3

In TCL SCRIPT, how to add dict or array

lr flag

I am trying to create an output format like keyword start_number last_number on a dictionary or array format. In my code, I used a dictionary, and the code is:

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
}

where the input is, or $data consist

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]

the expected output is In dictionary

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 }

or in array

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

this is what i am getting

{} {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}

Can anyone tell me what wrong with this code? Please mention any doubts related to my question or clarification in the comment section.

Nikita Kipriyanov avatar
za flag
Notice that the question is off topic on ServerFault. I answered it in the hope it will be closed-moved to the StackOverflow where it belongs and where the question and the answer will be valid.
Score:5
za flag

The first problem is that you print a line of an output for each single line of an input. While, as I understood your problem description, your output will not match the input line-by-line. So, at least the last puts is misplaced; it could be useful for the debug, but not for the output of the final result.

Second, you re-set key_start_end_data every cycle iteration to an empty dict. Probably you wanted to do that only before the cycle or when it switches to a new keyword? Also, before resetting it you have to copy its resulting value to some non-volatile variable, but you didn't used keyword_numbers for anything. Was it intended for collecting the resulting data?

Third, this is wrong use of dict lappend. It is intended to append to a list which is the value of some dict item; you don't have such a structure nowhere and it is not useful for this problem. Probably you wanted to use dict set which replaces the dictionary value for the given key, or creates the key and sets its to the value, if it wasn't exist:

dict set key_start_end_data bit_start $number

Finally, while your code could be debugged, it is too verbose and has too many variables, so it's hard to read and to understand. Compare it with the following:

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 ...]} makes it to only process lines that matched the regexp. Just a safeguard. Then, if this keyword already happened before, it replaces its bit_start and bit_end with whatever it should be considering the current line; if the keyword is new, it creates it anew with both subelements set to the number in the current line. This code will successfully process much more relaxed input, for instance, you can shuffle the lines of an input and the result will still be the same. I wrapped long lines; this is not necessary, but just looks better here.

I didn't processed the output to output lines. To do that, instead of last single puts, you can do the following:

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

It puts values in TCL's dict format, without colons

Score:3
fo flag

Similar approach to @Nikita, for comparison. Nikita's is better if the numbers may be unordered.

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}}
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.