2017-01-30 10 views
1

Hier ist mein Ausgangspunkt.Mit Golang CSV lesen, Spalten neu anordnen und Ergebnis in eine neue CSV mit Concurrency schreiben

Es ist ein Golang-Skript, in einem CSV mit 3 Spalten zu lesen, die Spalten neu anordnen und das Ergebnis in eine neue CSV-Datei schreiben.

package main 

import (
    "fmt" 
    "encoding/csv" 
    "io" 
    "os" 
    "math/rand" 
    "time" 
) 

func main(){ 
    start_time := time.Now() 

    // Loading csv file 
    rFile, err := os.Open("data/small.csv") //3 columns 
    if err != nil { 
    fmt.Println("Error:", err) 
    return 
    } 
    defer rFile.Close() 

    // Creating csv reader 
    reader := csv.NewReader(rFile) 

    lines, err := reader.ReadAll() 
    if err == io.EOF { 
     fmt.Println("Error:", err) 
     return 
    } 

    // Creating csv writer 
    wFile, err := os.Create("data/result.csv") 
    if err != nil { 
     fmt.Println("Error:",err) 
     return 
    } 
    defer wFile.Close() 
    writer := csv.NewWriter(wFile) 

    // Read data, randomize columns and write new lines to results.csv 
    rand.Seed(int64(time.Now().Nanosecond())) 
    var col_index []int 
    for i,line :=range lines{ 
     if i == 0 { 
     //randomize column index based on the number of columns recorded in the 1st line 
     col_index = rand.Perm(len(line)) 
    } 
    writer.Write([]string{line[col_index[0]], line[col_index[1]], line[col_index[2]]}) //3 columns 
    writer.Flush() 
} 

//print report 
fmt.Println("No. of lines: ",len(lines)) 
fmt.Println("Time taken: ", time.Since(start_time)) 

} 

Frage:

  1. Ist mein Code idiomatische für Golang?

  2. Wie kann ich diesem Code Parallelität hinzufügen?

+1

Sie können nicht einzelne Dateien gleichzeitig lesen oder schreiben, und wenn die Datenverarbeitung so viel schneller als die IO ist, hat es wenig Vorteile, das Lesen einer Datei gleichzeitig mit dem Schreiben einer anderen Datei zu machen. Wenn die Dateien riesig sind, kann es sich lohnen, aber zuerst ein funktionierendes Beispiel, um die Grundlagen zu verstehen. – JimB

+3

Dies ist möglicherweise besser für [codereview.stackexchange.com] (http://codereview.stackexchange.com/) geeignet. – icza

+0

@ JimB Ah, ich wusste nicht, dass das Lesen/Schreiben von Dateien nicht gleichzeitig möglich ist. Wenn ich meine Randomisierung von Spalten als ein separates Verfahren, z. func RandomizeColumns ([] string), könnte ich mein Reader-Objekt in 2 Streams teilen und RandomizeColumns() gleichzeitig anwenden? I.e. kann ich ein csv.Reader() Objekt in 2 teilen? –

Antwort

0

Ihr Code ist OK. Es gibt keinen Grund für Nebenläufigkeit. Aber Sie können zumindest die Speicherbedarfsänderung im laufenden Betrieb reduzieren. Verwenden Sie einfach Read() anstelle von ReadAll(), um die Zuweisung von Slice für die Loch-Eingabedatei zu vermeiden.

for line, err := reader.Read(); err == nil; line, err = reader.Read(){ 
    if err = writer.Write([]string{line[col_index[0]], line[col_index[1]], line[col_index[2]]}); err != nil { 
      fmt.Println("Error:", err) 
      break 
    } 
    writer.Flush() 
} 
+0

Danke für die Verbesserung! Ich halte Ihre Antwort für eine angemessene Antwort auf meine Frage. Ich bin ein wenig enttäuscht, dass dieser Anwendungsfall keine Nebenläufigkeit erfordert, aber ich werde nach einer anderen Übung suchen, um das zu üben. –

0

Bewegen Sie den col_index Initialisierung außerhalb des Schreibschleife:

if len(lines) > 0 { 
    //randomize column index based on the number of columns recorded in the 1st line 
    col_index := rand.Perm(len(lines[0])) 
    newLine := make([]string, len(col_index)) 

    for _, line :=range lines[1:] { 
     for from, to := range col_index { 
      newLine[to] = line[from] 
     } 
     writer.Write(newLine) 
     writer.Flush() 
    } 
} 

Parallelität zu verwenden, müssen Sie nicht reader.ReadAll verwenden. Erstellen Sie stattdessen eine Goroutine, die reader.Read aufruft, und schreiben Sie die Ausgabe auf einen Kanal, der das Array lines ersetzen würde. Die Hauptgoroutine würde den Kanal lesen und den Shuffle und den Schreibvorgang ausführen.

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, meinen Code zu überprüfen + eine mögliche Lösung mit Nebenläufigkeit zu erklären. –

Verwandte Themen