bharath kumar
bharath kumar

Reputation: 165

Array assignment in Tcl from *csv input file

I have a *csv file in which the data is as follows.

$cat file1.csv

"power_domains"    "VDD1#1#T"  "VDD1#1#B"  "VDD1#2#L"  "VDD1#2#R" 
 block1               6           6           6            6
 block2               0           3           2            4
 block3/a             2           2           1            1

In the above file . I want to assign the data as follows

block1(VDD1#1#T) = 6 , block1(VDD1#1#B) = 6 , block1(VDD1#2#L) = 6 , block1(VDD1#2#R)=6

block2(VDD1#1#T) = 0 ,  block2(VDD1#1#B) = 3 , block2(VDD1#2#L) = 2 , block2(VDD1#2#R)=4


block3/a(VDD1#1#T) = 2 ,  block3/a(VDD1#1#B) = 2 , block3/a(VDD1#2#L) = 1 , block3/a (VDD1#2#R)=1

To assign the data as above I have tried the following code:

if { [file exists .tmp.PG_Ring] == 1} {
    set fp_ring [open .tmp.PG_Ring r]
    set fp_ring_data [read $fp_ring]
    set fp_ring_row_data [split $fp_ring_data "\n"]
    foreach PG_Ring_row1 $fp_ring_row_data {
    set PG_Ring_row [regexp -inline -all {\S+} PG_Ring_row1]
    set PG_Ring_row [string map  { "\"" "" "\{" "" "\}" "" } $PG_Ring_row1]
    set  pg_ring_column [lindex $PG_Ring_row 0]
    set Rings_distance 5
    set pg_ring_flag [string index $PG_Ring_row 0]
    if { $pg_ring_flag != "#" && $pg_ring_flag != "" } {
            if { [ string match -nocase  "Rings_distance" $pg_ring_column ] }  {
            set Rings_distance [lindex $pg_ring_column 1]
            } elseif { [ string match -nocase "power_domains" $pg_ring_column ] }  {
            set no_ring_domains [llength  $PG_Ring_row ]
            #array set ring_domains [lrange $PG_Ring_row 1 end]
            set i 1
            while  {$i < $no_ring_domains} {
            set power_domain($i) [lindex $PG_Ring_row $i]
            puts "$i $power_domain($i)"                             
            incr i
            }
            }
    set j 1
    puts test
    puts $no_ring_domains
    puts $pg_ring_column
    while { $j < $no_ring_domains } {
    **set ($pg_ring_column)($power_domain($j))  [lindex $PG_Ring_row $j**]
    incr j
    puts "$($pg_ring_column)($power_domain($j))  "
    }

In the above code arrays I am unable to assign:

 *set ($pg_ring_column)($power_domain($j))  [lindex $PG_Ring_row $j**

This statement is not working. Could you please help me assign the arrays in TCL.

Upvotes: 2

Views: 1141

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137717

When handling CSV data, you're advised to use the csv package in Tcllib. That's got a command to read the data into a struct::matrix (another Tcllib package).

package require struct::matrix
package require csv

# Read it in
set m [struct::matrix]
set f [open "file1.csv"]
csv::read2matrix $f $m
close $f

# Now use the matrix ops to work with it.
set titles [$m get row 0]
set domains [$m get column 0]
# ...

# Write it out
set f [open "file2.csv" w]
csv::writematrix $m $f
close $f

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 247012

Dynamic array names are going to give you lots of pain. Better would be to use a dict or use an array and fake the multidimensional aspect:

array set data {}
set fid [open "file1.csv" r]
set header [regexp -all -inline {\S+} [regsub -all {"} [gets $fid] ""]]
while {[gets $fid line] != -1} {
    set fields [regexp -all -inline {\S+} $line]
    set block [lindex $fields 0]
    for {set i 1} {$i < [llength $fields]} {incr i} {
        set data($block,[lindex $header $i]) [lindex $fields $i]
    }
}
close $fid
parray data

outputs

data(block1,VDD1#1#B)   = 6
data(block1,VDD1#1#T)   = 6
data(block1,VDD1#2#L)   = 6
data(block1,VDD1#2#R)   = 6
data(block2,VDD1#1#B)   = 3
data(block2,VDD1#1#T)   = 0
data(block2,VDD1#2#L)   = 2
data(block2,VDD1#2#R)   = 4
data(block3/a,VDD1#1#B) = 2
data(block3/a,VDD1#1#T) = 2
data(block3/a,VDD1#2#L) = 1
data(block3/a,VDD1#2#R) = 1

Upvotes: 2

Related Questions