🦁
GoでSetを扱うには?JavaのようなSetを実現する方法
初めに
GoではJavaのような組み込みの Set
型は提供されていません。しかし、ちょっとした工夫で簡単にSetのような振る舞いを実現することができます。
この記事では、GoでSetを扱うためにmap
を活用してSetを再現する方法と、ライブラリのgo-setを使用する方法について解説します。
Setとは?
**Set(集合)**は、重複を許さず、順序を持たないデータ構造です。
Javaなどの言語では HashSet
や TreeSet
のようなクラスが提供されており、直感的に使うことができます。
一方、Goでは組み込みのSet型がないため、map
を使用してSetを再現するか、ライブラリを使用して扱います。
mapを使用してSetを再現する
標準機能でSetを作るには、以下のように map[T]struct{}
を使います。
package main
import "fmt"
func main() {
s := make(map[string]struct{})
// 要素の追加
s["apple"] = struct{}{}
s["apple"] = struct{}{}
s["banana"] = struct{}{}
s["orange"] = struct{}{}
// 存在チェック
if _, exists := s["apple"]; exists {
fmt.Println("apple は存在します")
}
// 要素の削除
delete(s, "banana")
// セット内の全要素を表示
for v := range s {
fmt.Println("item:", v)
}
}
実行結果
go run main.go
apple は存在します
item: apple
item: orange
ライブラリのgo-setを使用する
Setを扱えるライブラリはいくつかありますが、go-setでSetを扱います。
package main
import (
"fmt"
"github.com/scylladb/go-set/strset"
)
func main() {
s := strset.New()
// 要素の追加
s.Add("apple")
s.Add("apple")
s.Add("banana")
s.Add("orange")
// 存在チェック
if s.Has("apple") {
fmt.Println("apple は存在します")
}
// 要素の削除
s.Remove("banana")
// セット内の全要素を表示
for _, v := range s.List() {
fmt.Println("item:", v)
}
}
実行結果
go run main.go
apple は存在します
item: apple
item: orange
最後に
いつもはmap
を用いてSetを扱っていましたが、go-setの方が値の追加・削除・存在チェックのコードが少しシンプルで見やすく感じました。
ただ、重複チェック的な用途のためだけにライブラリを入れるのも少し微妙な気がするので、Goの標準機能で追加されて欲しいな、という思いはあります。
Discussion