読者です 読者をやめる 読者になる 読者になる

golangでコマンドラインツールを作る #5 配列をまとめる

f:id:masato47744:20150816150451p:plain

その4の続き

セクション名をまとめて表示する

READMEにこうなってほしいコマンドを先に書いた。 とりあえずどんなセクションがあるかは見たいかなと思ったので、

xgodeproj show project.pbxprojってやったらセクション名一覧が表示されるといいかもと思ったのでそれをやってみる。

goで配列を作って、重複を許さないようにして、適当にsortして表示するみたいなのやりたい。 このサイトよさそう。

配列の定義の仕方

配列の定義の仕方から調べないとだけど、固定長のやつのことを配列っていって、可変長のやつをスライスっていうらしい。 スライスを使っといた方がいいってことで、こう宣言する。

a := []string{}

で、あとは、これにisaのvalueを代入してく。append(スライス, 値)って書いてこいつが新しい配列を返してくる。 そして、それを自分に代入する。これはなんか直感的じゃない気がするな。

a = append(a, v)

最後に重複を取り除く。 これは、 golang-setってライブラリで実現できるようだ。

s := set.NewSetFromSlice(a)

しかし、[]stringが入らない。[]interface{}じゃないとダメなようだ。うーむ。

スライスから重複を取り除く

ということで重複を取り除く別の方法探す。パフォーマンスとか全く考えずにすでに配列に存在してたら、 追加しないでいいかと思って、containsみたいな関数ないかなと思って探してもないっぽい。 ありそうなのに標準で用意しないっていうのは何かポリシーでもあるんだろうか。

go - Contains method for a slice - Stack Overflow

しょうがないので、contains関数作る。

func contains(s []string, e string) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}

そして、愚直にisaのキーの値を重複なしで突っ込む。

for k, v := range mm.(map[string]interface{}) {
    if k == "isa" && !contains(ss, v.(string)) {
        ss = append(ss, v.(string))
    }
}

ソートもしておきたいのでどうやるのかなーと見ると、これは標準のパッケージがあるようだ。 これでOK。破壊的メソッドしかないっぽいのが気になる。

sort.Strings(s)

そして、重複抜きでそれっぽいのできた。

$ xgodeproj show project.pbxproj
PBXBuildFile
PBXContainerItemProxy
PBXFileReference
PBXFrameworksBuildPhase
PBXGroup
PBXNativeTarget
PBXProject
PBXResourcesBuildPhase
PBXSourcesBuildPhase
PBXTargetDependency
PBXVariantGroup
XCBuildConfiguration
XCConfigurationList

ここまでの感想

  • GoTourでスライスってなんか難しい気がしてたけど、可変長の配列ってだけ覚えてればよさそう?
  • golang-setがないって言われて気軽のgo getすればいいっての、だんだん慣れてきた。
  • interface{}っていうのが何でも入る可能性のある型みたいに使われてるってことが理解できてきた。
  • containsみたいなどう見ても使いそうなやつが用意されてないのなんでだろう?
  • 結構破壊的なメソッドが多いというかそれしか用意されてない感じな気がする
  • scalaのvalみたいな再代入禁止な宣言ができないの違和感感じた
  • スライスをfilter関数とかmap関数とかやりたいけどないのもそういうポリシーなのかな?

その6