下面的Go代码读取10,000条记录的CSV(时间戳times和浮点数values),对数据进行一些操作,然后将原始值以及的附加列写入到另一个CSV中score。但是,它的运行速度非常慢(例如,数小时,但大部分时间是calculateStuff()),我很好奇我可以处理的CSV读取/写入是否效率低下。
times
values
score
calculateStuff()
package main import ( "encoding/csv" "log" "os" "strconv" ) func ReadCSV(filepath string) ([][]string, error) { csvfile, err := os.Open(filepath) if err != nil { return nil, err } defer csvfile.Close() reader := csv.NewReader(csvfile) fields, err := reader.ReadAll() return fields, nil } func main() { // load data csv records, err := ReadCSV("./path/to/datafile.csv") if err != nil { log.Fatal(err) } // write results to a new csv outfile, err := os.Create("./where/to/write/resultsfile.csv")) if err != nil { log.Fatal("Unable to open output") } defer outfile.Close() writer := csv.NewWriter(outfile) for i, record := range records { time := record[0] value := record[1] // skip header row if i == 0 { writer.Write([]string{time, value, "score"}) continue } // get float values floatValue, err := strconv.ParseFloat(value, 64) if err != nil { log.Fatal("Record: %v, Error: %v", floatValue, err) } // calculate scores; THIS EXTERNAL METHOD CANNOT BE CHANGED score := calculateStuff(floatValue) valueString := strconv.FormatFloat(floatValue, 'f', 8, 64) scoreString := strconv.FormatFloat(prob, 'f', 8, 64) //fmt.Printf("Result: %v\n", []string{time, valueString, scoreString}) writer.Write([]string{time, valueString, scoreString}) } writer.Flush() }
我正在寻求帮助,以使此CSV读/写模板代码尽快。对于此问题的范围,我们不必担心该calculateStuff方法。
calculateStuff
您先将文件加载到内存中,然后再对其进行处理,这对于大文件而言可能会很慢。
您需要循环并一次调用.Read和处理一行。
.Read
func processCSV(rc io.Reader) (ch chan []string) { ch = make(chan []string, 10) go func() { r := csv.NewReader(rc) if _, err := r.Read(); err != nil { //read header log.Fatal(err) } defer close(ch) for { rec, err := r.Read() if err != nil { if err == io.EOF { break } log.Fatal(err) } ch <- rec } }() return }
playground
//请注意,它大致基于DaveC的评论。