Skip to content

Instantly share code, notes, and snippets.

@200sc
Created April 12, 2019 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 200sc/3400b24fd232a436b990bd23ce81b880 to your computer and use it in GitHub Desktop.
Save 200sc/3400b24fd232a436b990bd23ce81b880 to your computer and use it in GitHub Desktop.
Convert csvs with rows of fields to rows of objects
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
)
type Record struct {
key string
value string
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run convert.go example.csv")
return
}
input := os.Args[1]
f, err := os.Open(input)
if err != nil {
fmt.Println("Error opening input file", err)
return
}
r := csv.NewReader(f)
// Fields maps object ids to sets of defined key,value pairs
fields := make(map[int][]Record)
uniqueKeys := make(map[string]struct{})
for record, err := r.Read(); err == nil; record, err = r.Read() {
if len(record) < 3 {
fmt.Println("Unexpected short record set", record)
return
}
id, err := strconv.Atoi(record[0])
if err != nil {
fmt.Println("Expected integer ID for record", record)
return
}
fields[id] = append(fields[id], Record{record[1], record[2]})
uniqueKeys[record[1]] = struct{}{}
}
i := 1
keyIndices := make(map[string]int)
for k := range uniqueKeys {
keyIndices[k] = i
i++
}
outFile, err := os.Create("converted" + input)
if err != nil {
fmt.Println("Error opening output file", err)
return
}
w := csv.NewWriter(outFile)
headers := make([]string, len(keyIndices)+1)
headers[0] = "id"
for k, i := range keyIndices {
headers[i] = k
}
w.Write(headers)
for id, records := range fields {
toWrite := make([]string, len(keyIndices)+1)
toWrite[0] = strconv.Itoa(id)
for _, record := range records {
toWrite[keyIndices[record.key]] = record.value
}
w.Write(toWrite)
}
w.Flush()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment