Tcl文件内容处理

huangapple go评论61阅读模式
英文:

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内尝试了多种方法,但没有帮助我获得所需的值 Tcl文件内容处理

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 Tcl文件内容处理

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.

huangapple
  • 本文由 发表于 2023年6月1日 00:59:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76375807.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定