i have csv file containing many rows , columns 2 of similar to:
horizontal-1 acc. filename horizontal-2 acc. filename rsn88_sfern_fsd172.at2 rsn88_sfern_fsd262.at2 rsn164_impvall.h_h-cpe147.at2 rsn164_impvall.h_h-cpe237.at2 rsn755_lomap_cyc195.at2 rsn755_lomap_cyc285.at2 rsn1083_northr_gle170.at2 rsn1083_northr_gle260.at2 rsn1614_duzce_1061-n.at2 rsn1614_duzce_1061-e.at2 rsn1633_manjil_abbar--l.at2 rsn1633_manjil_abbar--t.at2 rsn3750_capemend_lfs270.at2 rsn3750_capemend_lfs360.at2 rsn3757_landers_npf090.at2 rsn3757_landers_npf180.at2 rsn3759_landers_wwt180.at2 rsn3759_landers_wwt270.at2 rsn4013_sansimeo_36258021.at2 rsn4013_sansimeo_36258111.at2 rsn4841_chuetsu_65004ns.at2 rsn4841_chuetsu_65004ew.at2 rsn4843_chuetsu_65006ns.at2 rsn4843_chuetsu_65006ew.at2 rsn4844_chuetsu_65007ns.at2 rsn4844_chuetsu_65007ew.at2 rsn4848_chuetsu_65011ns.at2 rsn4848_chuetsu_65011ew.at2
in csv file wanna headers "horizontal-1 acc. filename , horizontal-2 acc. filename" , line line names of each row under these headers 1 @ time ?
any suggestion ?
thanks rg.
package require csv package require struct::matrix ::struct::matrix m m add columns 2 set chan [open data.csv] ::csv::read2matrix $chan m close $chan lassign [m row 0] header1 header2 {set r 1} {$r < [m rows]} {incr r} { puts -nonewline [format {%s = %-30s } $header1 [m cell 0 $r]] puts [format {%s = %s} $header2 [m cell 1 $r]] } m destroy
i find easiest way deal csv data sets using matrix
. matrix
sort of two-dimensional vector built-ins searching, sorting , rearranging columns , rows.
first, create matrix , call m
. have 2 columns beginning, no rows yet.
::struct::matrix m m add columns 2
open channel read data file. pass channel , matrix name ::csv::read2matrix
command. command read csv data , create matrix row each data row. data fields stored in columns.
set chan [open data.csv] ::csv::read2matrix $chan m close $chan
to header strings, retrieve row 0.
lassign [m row 0] header1 header2
to iterate on data rows, go 1 (if didn't have headers, 0) under m rows
, number of rows in matrix.
there handy report
facility works matrices, i'll use for
loop here. i'm guessing how want data presented:
for {set r 1} {$r < [m rows]} {incr r} { puts -nonewline [format {%s = %-30s } $header1 [m cell 0 $r]] puts [format {%s = %s} $header2 [m cell 1 $r]] }
if you're done matrix, might destroy it.
m destroy
solution specific problem in comments.
package require csv package require struct::matrix ::struct::matrix m set chan [open foo.csv] ::csv::read2matrix $chan m , auto close $chan set f1 [m search column 0 "result id"] set headerrow [lindex $f1 0 1] set f2 [m search rect 0 $headerrow 0 [expr {[m rows] - 1}] ""] set f3 [m search row $headerrow "horizontal-1 acc. filename"] set f4 [m search row $headerrow "horizontal-2 acc. filename"] set top [expr {$headerrow + 1}] set bottom [expr {[lindex $f2 0 1] - 1}] set left [lindex $f3 0 0] set right [lindex $f4 0 0] puts [format {vector=[ %s ]} [concat {*}[m rect $left $top $right $bottom]]] m destroy
obviously, need change filename correct name. there no error handling: in such simple script it's better have script fail , correct whatever went wrong.
solution second problem, comments below:
package require csv package require struct::matrix ::struct::matrix m set chan [open _searchresults.csv] ::csv::read2matrix $chan m , auto close $chan set f1 [m search column 0 {result id}] set headerrow [lindex $f1 0 1] set f2 [m search -glob rect 0 $headerrow 0 [expr {[m rows] - 1}] { these*}] set numofrow [lindex $f2 0 1] set headercol1 [m search row $headerrow { horizontal-1 acc. filename}] set headercol2 [m search row $headerrow { horizontal-2 acc. filename}] set indexheaderh1col [lindex $headercol1 0 0] set indexheaderh2col [lindex $headercol2 0 0] set rows [m rect $indexheaderh1col [expr {$headerrow+1}] $indexheaderh2col [expr {$numofrow-1}]] set rows [lmap row $rows { lassign $row b list [string trim $a] [string trim $b] }] foreach row $rows { puts [format {%-30s %s} {*}$row] } puts [format {vector=[ %s ]} [concat {*}$rows]]
comments:
- you don't need set number of columns if use
read2matrix
auto
- in file, there no empty cell after table. instead, need search string beginning " these"
- since each cell holds space character followed value, need trim off space around value, otherwise concatenation go wrong. part
lmap
command fixes that - always brace expressions
documentation: + (operator), - (operator), < (operator), chan, close, concat, csv (package), expr, for, format, incr, lassign, lindex, lmap (for tcl 8.5), lmap, open, package, puts, set, struct::matrix (package), {*} (syntax)
Comments
Post a Comment