GoでSet型を実現する場合の選択肢
はじめに
Go言語には標準で Set 型がありません。
ここでは2通りの実現方法を検討してみます。
1. map ✕ structで実現する
mapのフィールドに空のstructを使ってsetを定義します。
structは何もフィールドを持たない場合、サイズは0になるのでコストがかかりません。
A struct{} takes up no space.
※golang-nutsにて説明されています。
package main import . "fmt" func main() { list := []string{ "test1", "test2", "test3", } set := make(map[string]struct{}) for _, v := range list { set[v] = struct{}{} } Printf("%#v\n", set) }
map[string]struct {}{ "test1":struct {}{}, "test2":struct {}{}, "test3":struct {}{} }
2. ライブラリを使う
golang-setというライブラリがいけてそうなので紹介します。
2017/02/03にもコミットがあり、わりと最近も更新されているようです。
github.com
GoDocはこちら
関数はかなり充実していました。
package main import ( . "fmt" "github.com/deckarep/golang-set" ) func main() { s1 := mapset.NewSet() s1.Add("1") s1.Add("2") s1.Add(3) s1.Add(4) print(s1) // Set{4, "1", "2", 3} // slice → set slice := []interface{}{"1", "2", 3, "5"} s2 := mapset.NewSetFromSlice(slice) print(s2) // Set{"5", "1", "2", 3} // set同士の結合 all := s1.Union(s2) print(all) // Set{3, 4, "1", "2", "5"} print(all.Difference(s1)) // Set{"5"} // 要素数確認 Println(s1.Cardinality()) // 4 Println(s2.Cardinality()) // 4 Println(all.Cardinality()) // 5 // 存在チェック Println(s1.Contains(1)) // false Println(s1.Contains("1")) // true // 要素削除 s1.Remove(4) print(s1) // Set{"1", "2", 3} // 要素全削除 s1.Clear() print(s1) // Set{} } func print(s mapset.Set) { Printf("%#v\n", s) }
まとめ
簡易的でよければ 1 で、
凝った使い方をしたければ 2 という選択がよさそうです。
おしまい。