2012-07-13 15 views
12

Plik names.txt składa się z wielu nazwisk w formie:strings.Split Przejdź

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

Czy ktoś wie, jak podzielić ciąg tak, że poszczególne nazwy oddzielone przecinkami?

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

Poniższy kod dzieli przecinkiem i pozostawia cudzysłowy wokół nazwy, co jest znakiem ucieczki, aby podzielić się z ". Czy można to zrobić w jednym wyrażeniu Split, dzieląc "," i pozostawiając przecinek do oddzielenia?

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) 

} 

Nawiasem mówiąc, jest to część projektu Euler problem # 22. http://projecteuler.net/problem=22

Odpowiedz

18

Odpowiedź Jeremy'ego jest w zasadzie poprawna i spełnia dokładnie to, o co prosiłeś. Format pliku "names.txt" jest jednak dobrze znany i nosi nazwę CSV (wartości rozdzielone przecinkami). Na szczęście Go jest dostarczany z pakietem encoding/csv (który jest częścią standardowej biblioteki) do łatwego dekodowania i kodowania takich formatów. Oprócz rozwiązania + Jeremy's, ten pakiet będzie również podawał dokładne komunikaty o błędach, jeśli format jest nieprawidłowy, obsługuje rekordy wielowierszowe i wykonuje odpowiednią liczbę cytowanych ciągów.

Podstawowe użycie wygląda następująco:

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 
    } 
} 

Istnieje również metoda ReadAll które mogłyby uczynić program jeszcze krótszy, przy założeniu, że cały plik pasuje do pamięci.

Aktualizacja: Dystroy zaznaczył, że Twój plik ma tylko jedną linię. Czytelnik CSV działa dobrze, że zbyt, ale po mniej ogólne rozwiązanie powinno być wystarczające:

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

To nie jest plik csv, ponieważ istnieje tylko jeden wiersz: http://projecteuler.net/project/names.txt –

+0

Och, masz rację. Jest to plik CSV z pojedynczą linią :) – tux21b

+1

Plus jeden do użytku z Fscanf :-) –

9

Podział nie usuwa znaki od podciągów. Twój podzielone jest w porządku, po prostu trzeba przetworzyć kawałek potem z strings.Trim (Val, „\” „).

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

Teraz arr będzie miał początkowe i końcowe” s usuwane.

+2

Należy pamiętać, że to nie będzie działać dla: '„Smithe, P.”,„Kowalski, J.” ' – Timmmm