2021-04-26

Transpose File

You are given a text file. Write a script to transpose the contents of the given file.

Input File

name,age,sex
Mohammad,45,m
Joe,20,m
Julie,35,f
Cristina,10,f

Output:

name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

處理程式:

package require struct::matrix

set infile [open "input.dat" r]

# Read data
set filedata [list]
while { [gets $infile line] >= 0 } {
    set mylist [split $line ","]
    lappend filedata $mylist
}
close $infile

set maxrow [llength $filedata]
set maxcol [llength [lindex $filedata 0]]

::struct::matrix data
for {set i 0} {$i < $maxcol} {incr i} {
    data add column
}

for {set i 0} {$i < $maxrow} {incr i} {
    data add row [lindex $filedata $i]
}

data transpose

set rows [data rows]
for {set row 0} {$row < $rows} {incr row} {
    set mylist [data get row $row]
    set result [join $mylist ","]
    puts $result
}
data destroy

或者使用 tcllib csv 配合 struct::matrix 來處理:

package require csv
package require struct::matrix

::struct::matrix data
set infile [open "input.dat" r]
csv::read2matrix $infile data  , auto
close $infile

data transpose

set rows [data rows]
for {set row 0} {$row < $rows} {incr row} {
    set mylist [data get row $row]
    set result [join $mylist ","]
    puts $result
}
data destroy

或者使用 tclcsv 讀出資料,再配合 struct::matrix 來處理:

package require tclcsv
package require struct::matrix

set infile [open "input.dat" r]
set filedata [tclcsv::csv_read $infile]
close $infile

set maxrow [llength $filedata]
set maxcol [llength [lindex $filedata 0]]

::struct::matrix data
for {set i 0} {$i < $maxcol} {incr i} {
    data add column
}

for {set i 0} {$i < $maxrow} {incr i} {
    data add row [lindex $filedata $i]
}

data transpose

set rows [data rows]
for {set row 0} {$row < $rows} {incr row} {
    set mylist [data get row $row]
    set result [join $mylist ","]
    puts $result
}
data destroy

也可以使用 SQLite3 In-Memory Database 來處理,首先將資料儲存到表格中,然後依序選出以後再印出來:

package require tdbc::sqlite3
tdbc::sqlite3::connection create db ":memory:"

set statement [db prepare {create table mydata (name TEXT, age integer, sex char(1))}]
$statement execute
$statement close

set infile [open "input.dat" r]

# Read first line, field name
gets $infile line
set titles [split $line ","]

# Read data
while { [gets $infile line] >= 0 } {
    set mylist [split $line ","]
    set name [lindex $mylist 0]
    set age [lindex $mylist 1]
    set sex [lindex $mylist 2]
    
    set statement [db prepare {insert into mydata values (:name, :age, :sex)}]
    $statement execute
    $statement close
}
close $infile

# Output
for {set i 0} {$i < [llength $titles]} {incr i} {
    set field [lindex $titles $i]
    puts -nonewline "$field"
    set statement [db prepare "select $field from mydata"]
    
    $statement foreach row {
        puts -nonewline ",[dict get $row $field]"
    }

    $statement close
    puts ""
}
db close

沒有留言: