英文:
Tcl file content processing
问题
我有一个.csv文件,其中包含以下数据
January,A1,100
January,A2,200
January,A3,300
January,B1,100
January,B2,300
February,A1,100
February,A2,200
February,B2,200
March,C1,200
March,B1,400
April,D1,100
我需要从磁盘读取上述.csv文件,对其进行处理,并显示其摘要如下。如何将上述原始数据转换为以下数值?
月份 A B
一月 600 400
二月 300 200
三月 0 400
四月 0 0
A的计算公式是:当索引1为A1/A2/A3时,索引2中的值的总和(如果不可用则为0)。
B的计算公式是:当索引1中的值为B1/B2/B3时,索引2中的值的总和(如果不可用则为0)。
我尝试过以下方法:
set file [open $loc r]
while {[gets $file sline] >=0} {
regsub {"(.*?),(.*?)"} $sLine {:} sLine
set lsLine [split $sLine ","]
set month [lindex $lsLine 0]
lappend mnList $month
set monthList [lsort -unique $mnList]
}
我已经找到了以下代码中的格式部分。
set Month $monthList
set A {600 300 0 0}
set B {400 200 400 0}
set formatStr {%15s%15s%15s}
puts [format $formatStr "Month" "A" "B"]
foreach month $Month a $A b $B {
puts [format $formatStr $month $a $b]
}
我很难从文件中计算A和B列的值。我在foreach month $monthList
内尝试了多种方法,但没有帮助我获得所需的值
P.S. 我对tcl和编程相当陌生。
英文:
I have a .csv file with below data
January,A1,100
January,A2,200
January,A3,300
January,B1,100
January,B2,300
February,A1,100
February,A2,200
February,B2,200
March,C1,200
March,B1,400
April,D1,100
I need to read the above .csv file from disk, process it and display it's summary as below. How do I convert the above raw data into below values?
Month A B
January 600 400
February 300 200
March 0 400
April 0 0
The formula for A is total of values in index 2 when index 1 is A1/A2/A3(0 if not available)
The formula for B is total of values in index 2 when index 1 values is B1/B2/B3(0 if not available)
What I tried:
set file [open $loc r]
while {[gets $file sline] >=0} {
regsub {"(.*?),(.*?)"} $sLine {:} sLine
set lsLine [split $sLine ","]
set month [lindex $lsLine 0]
lappend mnList $month
set monthList [lsort -unique $mnList]
}
I did figure out the formating part with below code.
set Month $monthList
set A {600 300 0 0}
set B {400 200 400 0}
set formatStr {%15s%15s%15s}
puts [format $formatStr "Month" "A" "B"]
foreach month $Month a $A b $B {
puts [format $formatStr $month $a $b]
}
I am having hard time calculating the values of A and B columns from the file. I tried multiple ways inside foreach month $monthList
but none helped me to get the values I need
P.S. Pretty new to tcl and coding
答案1
得分: 1
set file [open file.csv r]
set data {}
while {[gets $file line] != -1} {
lassign [split $line ,] month key value
dict update data $month monthData {
dict incr monthData [string range $key 0 0] $value
}
}
proc dictGetDef {dictValue key default} {
if {![dict exists $dictValue $key]} {
return $default
}
return [dict get $dictValue $key]
}
dict for {month monthData} $data {
puts [format {%-10s %5d %5d} $month [dictGetDef $monthData A 0] [dictGetDef $monthData B 0]]
}
January 600 400
February 300 200
March 0 400
April 0 0
Tcl 8.7 has dict getdef
natively, but better.
To restrict the accumulating to a set of specific keys can be done in several ways. Using switch
makes it quite explicit:
while {[gets $file line] != -1} {
lassign [split $line ,] month key value
switch -- $key {
A1 - A2 - A3 -
B1 - B2 - B3 {
dict update data $month monthData {
dict incr monthData [string range $key 0 0] $value
}
}
}
}
You give switch
pattern-body pairs. If the body is -
, then it falls through to the next body.
英文:
set file [open file.csv r]
set data {}
while {[gets $file line] != -1} {
lassign [split $line ,] month key value
dict update data $month monthData {
dict incr monthData [string range $key 0 0] $value
}
}
# $data contains:
# January {A 600 B 400} February {A 300 B 200} March {C 200 B 400} April {D 100}
proc dictGetDef {dictValue key default} {
if {![dict exists $dictValue $key]} {
return $default
}
return [dict get $dictValue $key]
}
dict for {month monthData} $data {
puts [format {%-10s %5d %5d} $month [dictGetDef $monthData A 0] [dictGetDef $monthData B 0]]
}
January 600 400
February 300 200
March 0 400
April 0 0
Tcl 8.7 has dict getdef
natively, but better.
To restrict the accumulating to a set of specific keys can be done is several ways. Using switch makes it quite explicit:
while {[gets $file line] != -1} {
lassign [split $line ,] month key value
switch -- $key {
A1 - A2 - A3 -
B1 - B2 - B3 {
dict update data $month monthData {
dict incr monthData [string range $key 0 0] $value
}
}
}
}
You give switch
pattern-body pairs. If the body is -
then it falls through to the next body.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论