Skip to content

Instantly share code, notes, and snippets.

@gunnaraasen
Created December 27, 2013 23:13
Show Gist options
  • Select an option

  • Save gunnaraasen/8153965 to your computer and use it in GitHub Desktop.

Select an option

Save gunnaraasen/8153965 to your computer and use it in GitHub Desktop.
Example program for merging a csv file with a much larger csv file. This program is specifically for merging voter addresses and precinct polling locations.
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"strings"
)
// Takes a list of polling locations and creates and index in memory
func indexcsv(fname string) (index map[string][]string, err error) {
// Open the precinct polling location file
fi, err := os.Open(fname)
if err != nil {
panic(err)
}
r := csv.NewReader(fi)
defer fi.Close()
// Make index and save the fields on the first line
index = make(map[string][]string)
index["fields"], err = r.Read()
if err != nil {
fmt.Println(err)
}
// Read through whole file line by line
for {
record, err := r.Read()
if err != nil {
if err == io.EOF {
return index, nil
}
return index, err
}
// Extract the state from the State/ZIP field
key := strings.Split(record[2], " ")[0]
// Extract the precinct number from the Precinct field
precinct := strings.Split(record[4], "-")
key = key + "-" + precinct[len(precinct)-1]
// Create an index of the key and record
index[key] = record
fmt.Println(record)
}
return index, nil
}
// Reads through voter location list line by line so that the whole
// file is not in memory at one time
func mergecsv(index map[string][]string, fname, output string) error {
// Open the voter address file
fi, err := os.Open(fname)
if err != nil {
panic(err)
}
r := csv.NewReader(fi)
defer fi.Close()
// Create a new file for the merged output
fo, err := os.Create(output)
if err != nil {
panic(err)
}
w := csv.NewWriter(fo)
defer fo.Close()
// Write the fields to output
w.Write([]string{"Voter Location", "", "", "", "", "", "",
"Polling Location", "", "", "", ""})
fields, err := r.Read()
if err != nil {
fmt.Println(err)
}
fields = append(fields, "Key")
for _, v := range index["fields"] {
fields = append(fields, v)
}
w.Write(fields)
// Read through the file line by line
for {
record, err := r.Read()
if err != nil {
if err == io.EOF {
w.Flush()
return w.Error()
}
return err
}
// Extract the state from the State field
otherkey := record[3]
// Extract the precinct number from the Precinct ID field
precinct := strings.Split(record[5], "-")
otherkey = otherkey + "-" + precinct[len(precinct)-1]
// Append the key to the voter address
record = append(record, otherkey)
// Look up the polling location in the index
indexRecord, ok := index[otherkey]
if ok == false {
// Write an error to the file lookup errors
w.Write(append(record, "No polling location found"))
continue
}
// Append polling location to the record and write to output
for _, v := range indexRecord {
record = append(record, v)
}
w.Write(record)
fmt.Println(record)
}
}
func main() {
// Index first csv file
index, err := indexcsv(os.Args[1])
if err != nil {
fmt.Println(err)
}
// Merge the index with the second csv file
// and write output to the third argument
mergecsv(index, os.Args[2], os.Args[3])
if err != nil {
fmt.Println(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment