总结csv的内容
Summarizing contents of csv
上下文
我正在创建一个小程序,它可以总结一团乱七八糟的账单的内容,它是 csv 格式的。
帐单有三列我感兴趣:
- 事件类型。在这里,我只对该列显示为 CHARGE
的行感兴趣
- 费用。不言自明。
- 资源名称,包含服务器和集群名称。格式为 servername.clustername.
想法是 select 标记为收费的行,先按集群拆分,然后按服务器名称拆分,然后汇总每个行的总成本。
我不禁觉得这应该很容易,但我已经为此摸不着头脑了一段时间,似乎就是想不通。在这一点上,我应该声明我是编程新手,而且是 GO 的新手。
这是我目前的情况:
package main
import (
"encoding/csv"
"log"
"os"
"sort"
"strings"
)
func main() {
rows := readBill("bill-2018-April.csv")
rows = calculateSummary(rows)
writeSummary("bill-2018-April-output", rows)
}
func readBill(name string) [][]string {
f, err := os.Open(name)
if err != nil {
log.Fatalf("Cannot open '%s': %s\n", name, err.Error())
}
defer f.Close()
r := csv.NewReader(f)
rows, err := r.ReadAll()
if err != nil {
log.Fatalln("Cannot read CSV data:", err.Error())
}
return rows
}
type charges struct {
impactType string
cost float64
resName string
}
func createCharges(rows [][]string){
charges:= []charges{}
for i,r:=range rows {
var c charges
c.impactType :=r [i][10]
c.cost := r [i][15]
c.resName := r [i][20]
charges = append()
}
return charges
}
因此,据我所知,我现在应该已经分离出我感兴趣的列(即第 10、15 和 20 列)。我目前所掌握的是否正确?
我将如何挑出读取 "CHARGE" 的行并按集群和服务器分割所有内容?
总结应该不会太棘手,但无论出于何种原因,这真的让我很困惑。
只需使用两个映射来存储每个服务器和每个集群的总和。由于您对整个 CSV 文件不感兴趣,而只对某些行感兴趣,因此阅读所有内容有点浪费。跳过您不关心的行:
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"strconv"
"strings"
)
func main() {
b := `
,,,,,,,,,,CHARGE,,,,,100.00,,,,,s1.c1
,,,,,,,,,,IGNORE,,,,,,,,,,
,,,,,,,,,,CHARGE,,,,,200.00,,,,,s2.c1
,,,,,,,,,,CHARGE,,,,,300.00,,,,,s3.c2
`
r := csv.NewReader(strings.NewReader(b))
byServer := make(map[string]float64)
byCluster := make(map[string]float64)
for i := 0; ; i++ {
row, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
if row[10] != "CHARGE" {
continue
}
cost, err := strconv.ParseFloat(row[15], 64)
if err != nil {
log.Fatalf("row %d: malformed cost: %v", i, err)
}
xs := strings.SplitN(row[20], ".", 2)
if len(xs) != 2 {
log.Fatalf("row %d: malformed resource name", i)
}
server, cluster := xs[0], xs[1]
byServer[server] += cost
byCluster[cluster] += cost
}
fmt.Printf("byServer: %+v\n", byServer)
fmt.Printf("byCluster: %+v\n", byCluster)
}
// Output:
// byServer: map[s2:200 s3:300 s1:100]
// byCluster: map[c1:300 c2:300]
上下文 我正在创建一个小程序,它可以总结一团乱七八糟的账单的内容,它是 csv 格式的。
帐单有三列我感兴趣:
- 事件类型。在这里,我只对该列显示为 CHARGE 的行感兴趣
- 费用。不言自明。
- 资源名称,包含服务器和集群名称。格式为 servername.clustername.
想法是 select 标记为收费的行,先按集群拆分,然后按服务器名称拆分,然后汇总每个行的总成本。
我不禁觉得这应该很容易,但我已经为此摸不着头脑了一段时间,似乎就是想不通。在这一点上,我应该声明我是编程新手,而且是 GO 的新手。
这是我目前的情况:
package main
import (
"encoding/csv"
"log"
"os"
"sort"
"strings"
)
func main() {
rows := readBill("bill-2018-April.csv")
rows = calculateSummary(rows)
writeSummary("bill-2018-April-output", rows)
}
func readBill(name string) [][]string {
f, err := os.Open(name)
if err != nil {
log.Fatalf("Cannot open '%s': %s\n", name, err.Error())
}
defer f.Close()
r := csv.NewReader(f)
rows, err := r.ReadAll()
if err != nil {
log.Fatalln("Cannot read CSV data:", err.Error())
}
return rows
}
type charges struct {
impactType string
cost float64
resName string
}
func createCharges(rows [][]string){
charges:= []charges{}
for i,r:=range rows {
var c charges
c.impactType :=r [i][10]
c.cost := r [i][15]
c.resName := r [i][20]
charges = append()
}
return charges
}
因此,据我所知,我现在应该已经分离出我感兴趣的列(即第 10、15 和 20 列)。我目前所掌握的是否正确?
我将如何挑出读取 "CHARGE" 的行并按集群和服务器分割所有内容?
总结应该不会太棘手,但无论出于何种原因,这真的让我很困惑。
只需使用两个映射来存储每个服务器和每个集群的总和。由于您对整个 CSV 文件不感兴趣,而只对某些行感兴趣,因此阅读所有内容有点浪费。跳过您不关心的行:
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"strconv"
"strings"
)
func main() {
b := `
,,,,,,,,,,CHARGE,,,,,100.00,,,,,s1.c1
,,,,,,,,,,IGNORE,,,,,,,,,,
,,,,,,,,,,CHARGE,,,,,200.00,,,,,s2.c1
,,,,,,,,,,CHARGE,,,,,300.00,,,,,s3.c2
`
r := csv.NewReader(strings.NewReader(b))
byServer := make(map[string]float64)
byCluster := make(map[string]float64)
for i := 0; ; i++ {
row, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
if row[10] != "CHARGE" {
continue
}
cost, err := strconv.ParseFloat(row[15], 64)
if err != nil {
log.Fatalf("row %d: malformed cost: %v", i, err)
}
xs := strings.SplitN(row[20], ".", 2)
if len(xs) != 2 {
log.Fatalf("row %d: malformed resource name", i)
}
server, cluster := xs[0], xs[1]
byServer[server] += cost
byCluster[cluster] += cost
}
fmt.Printf("byServer: %+v\n", byServer)
fmt.Printf("byCluster: %+v\n", byCluster)
}
// Output:
// byServer: map[s2:200 s3:300 s1:100]
// byCluster: map[c1:300 c2:300]