1. ホーム
  2. スクリプト・コラム
  3. ゴラン

2つのcsvの実装例をマージするために移動します。

2022-02-14 02:19:20

背景

普段はpython+pandasでファイルを扱っているのですが、これが実にいい香りなのです。しかし今日、突然goを使って2つのcsvファイルのマージを書くように言われ、2つのcsvをidでマージする必要があり、おおよそ以下のような感じです。

考え方は簡単で、まず2つのcsvファイルを読み込み、それらを繰り返し処理してidを比較し、同じならもう一方のファイルの内容を最初のファイルに追加するのです。次にmerge.csvを作成し、前のステップで取得したデータをcsvに書き込みます。

コードセクション

package main

import (
 "encoding/csv"
 "log"
 "os"

 "fmt"
)

func join(fileName1 string, fileName2 string) (row [][]string) {
 fs1, _ := os.Open(fileName1)
 r1 := csv.NewReader(fs1)
 content1, err := r1.ReadAll()
 if err ! = nil {
  log.Fatalf("can not readall, err is %+v", err)
 }

 fs2, _ := os.Open(fileName2)
 r2 := csv.NewReader(fs2)
 content2, err := r2.ReadAll()
 if err ! = nil {
  log.Fatalf("can not readall, err is %+v", err)
 }
 row = make([][]string, len(content1[1:]))

 for i, row1 := range content1[1:] {
  for _, row2 := range content2[1:] {
   if row1[0] == row2[0] {
    row[i] = append(row[i], row1[0], row1[1], row1[2], row2[1], row2[2])
   }
  }
 }
 return
}

func edit(filename string, row [][]string) {
 f, err := os.Create(filename)
 if err ! = nil {
  panic(err)
 }
 defer f.Close()

 //prevent garbled code
 f.WriteString("\xEF\xBB\xBF")
 w := csv.NewWriter(f)
 w.Write([]string{"ID", "name", "gender", "course", "score"})
 w.WriteAll(row)
 w.Flush()
}

func main() {
 row := join("1.csv", "2.csv")
 fmt.Println(row)
 edit("join.csv", row)
 fmt.Println("merge is done! ")
}

最適化

少量のデータであればこれで問題ないのですが、データ量が増えてくると、読み込み時のメモリフットプリントが増えるだけでなく、トラバーサル比較に非常に時間がかかるようになります。そこで最適化するために、行単位で読み込んだり、goのgoroutineを利用して速度を上げる方法を探したりします。残念なことに、go を書いてからずいぶん経つので、最初はスライスのことを忘れていました。

2つのcsvをマージするGoの実装に関するこの記事は、そのすべてです。Goのcsvのマージについては、スクリプトハウスの過去記事を検索するか、以下の関連記事を引き続き閲覧してください。