2012-07-13 11 views
12

Il file names.txt è composto da molti nomi sotto forma di:strings.Split in Go

"KELLEE","JOSLYN","JASON","INGER","INDIRA","GLINDA","GLENNIS" 

Qualcuno sa come dividere la stringa in modo che sia i singoli nomi separati da virgole?

KELLEE,JOSLYN,JASON,INGER,INDIRA,GLINDA,GLENNIS 

Il seguente codice divide da una virgola e lascia le virgolette intorno al nome, qual è il carattere di escape per dividere il ". Può essere eseguito in un'unica istruzione Split, dividendo "," e lasciando una virgola da separare?

package main 

import "fmt" 
import "io/ioutil" 
import "strings" 

func main() { 
     fData, err := ioutil.ReadFile("names.txt") // read in the external file 
    if err != nil { 
     fmt.Println("Err is ", err)  // print any error 
    } 
    strbuffer := string(fData) // convert read in file to a string 

    arr := strings.Split(strbuffer, ",") 

    fmt.Println(arr) 

} 

Tra l'altro, questo è parte del Project Euler problema # 22. http://projecteuler.net/problem=22

risposta

18

La risposta di Jeremy è fondamentalmente corretta e fa esattamente quello che hai chiesto. Ma il formato del tuo file "names.txt" è in realtà ben noto e si chiama CSV (valori separati da virgola). Fortunatamente, Go viene fornito con un pacchetto encoding/csv (che fa parte della libreria standard) per la decodifica e la codifica di tali formati facilmente. Oltre alla soluzione + di Jeremy, questo pacchetto fornirà anche messaggi di errore esatti se il formato non è valido, supporta i record a più righe e annulla l'appropriazione delle stringhe tra virgolette.

L'uso di base è simile al seguente:

package main 

import (
    "encoding/csv" 
    "fmt" 
    "io" 
    "os" 
) 

func main() { 
    file, err := os.Open("names.txt") 
    if err != nil { 
     fmt.Println("Error:", err) 
     return 
    } 
    defer file.Close() 
    reader := csv.NewReader(file) 
    for { 
     record, err := reader.Read() 
     if err == io.EOF { 
      break 
     } else if err != nil { 
      fmt.Println("Error:", err) 
      return 
     } 

     fmt.Println(record) // record has the type []string 
    } 
} 

V'è anche un metodo di ReadAll che potrebbe rendere il vostro programma ancora più breve, partendo dal presupposto che l'intero file si inserisce nella memoria.

Aggiornamento: dystroy ha appena sottolineato che il file ha solo una riga comunque. Il lettore CSV funziona bene anche per questo, ma il seguente, soluzione meno generale dovrebbe anche essere sufficiente:

for { 
    if n, _ := fmt.Fscanf(file, "%q,", &name); n != 1 { 
     break 
    } 
    fmt.Println("name:", name) 
} 
+0

Questo non è un file CSV in quanto esiste una sola riga: http://projecteuler.net/project/names.txt –

+0

Oh, hai ragione. È un file CSV con una riga singola :) – tux21b

+1

Più uno per l'uso di Fscanf :-) –

9

Split non rimuove i caratteri dalle sottostringhe. Il vostro split è bene non vi resta che elaborare la fetta in seguito con strings.Trim (val, "\" ").

for i, val := range arr { 
    arr[i] = strings.Trim(val, "\"") 
} 

Ora arr avrà parte anteriore e posteriore" s rimosso.

+2

Si noti che questo non funzionerà per: ' "Smithe, P.", "Bloggs, J." ' – Timmmm