An open API service indexing awesome lists of open source software.

https://github.com/devlights/hashset

Go言語用の汎用的なHashSet実装です。
https://github.com/devlights/hashset

go golang

Last synced: 5 months ago
JSON representation

Go言語用の汎用的なHashSet実装です。

Awesome Lists containing this project

README

          

# これは何?

Go言語用の汎用的なHashSet実装です。

Goでは標準ライブラリとしてHashSetは提供されていませんが、```map[T]struct{}```で同じことが出来るので基本的にそれで代用することが多いです。が、毎回同じ処理を書いているのでついでに簡易ライブラリにしたという経緯です。

## インストール

```bash
go get github.com/devlights/hashset@latest
```

## クイックスタート

```go
package main

import (
"fmt"
"github.com/devlights/hashset"
)

func main() {
// 新しい文字列集合を作成
fruits := hashset.New[string]()

// 要素を追加
fruits.Add("apple")
fruits.Add("banana")
fruits.Add("orange")

// 要素の存在を確認
fmt.Println(fruits.Contains("apple")) // true
fmt.Println(fruits.Contains("grape")) // false

// サイズを取得
fmt.Printf("集合のサイズ: %d\n", fruits.Size()) // 集合のサイズ: 3

// スライスに変換
fruitsSlice := fruits.ToSlice()
fmt.Printf("フルーツ: %v\n", fruitsSlice)
}
```

## API リファレンス

### 作成

```go
// 空の集合を作成
set := hashset.New[string]()

// 初期容量を指定して作成(パフォーマンス最適化のため)
set := hashset.NewWithCapacity[string](100)

// スライスから作成
items := []string{"apple", "banana", "orange"}
set := hashset.NewFromSlice(items)
```

### 基本操作

```go
// 単一要素を追加
set.Add("apple")

// 複数要素を追加
set.AddAll([]string{"banana", "orange"})

// 単一要素を削除
set.Remove("apple")

// 複数要素を削除
set.RemoveAll([]string{"banana", "orange"})

// 存在確認
exists := set.Contains("apple")

// 複数要素の確認
allExist := set.ContainsAll([]string{"apple", "banana"})
anyExist := set.ContainsAny([]string{"apple", "grape"})

// サイズ取得と空かどうかの確認
size := set.Size()
empty := set.IsEmpty()

// すべての要素をクリア
set.Clear()
```

### 変換と複製

```go
// スライスに変換
slice := set.ToSlice()

// コピーを作成
clone := set.Clone()
```

### 集合演算

```go
set1 := hashset.NewFromSlice([]string{"apple", "banana"})
set2 := hashset.NewFromSlice([]string{"banana", "orange"})

// 和集合 (A ∪ B)
union := set1.Union(set2) // {"apple", "banana", "orange"}

// 積集合 (A ∩ B)
intersection := set1.Intersection(set2) // {"banana"}

// 差集合 (A - B)
difference := set1.Difference(set2) // {"apple"}

// 対称差集合 ((A ∪ B) - (A ∩ B))
symDiff := set1.SymmetricDifference(set2) // {"apple", "orange"}
```

### 集合関係

```go
set1 := hashset.NewFromSlice([]string{"apple", "banana"})
set2 := hashset.NewFromSlice([]string{"apple", "banana", "orange"})

// set1がset2の部分集合かどうかを確認
isSubset := set1.IsSubsetOf(set2) // true

// set2がset1の上位集合かどうかを確認
isSuperset := set2.IsSupersetOf(set1) // true

// 集合が共通要素を持たないかどうかを確認
disjoint := set1.IsDisjoint(hashset.NewFromSlice([]string{"grape", "kiwi"})) // true

// 集合が等しいかどうかを確認
equal := set1.Equal(set1.Clone()) // true
```

### 反復処理

```go
// 要素を反復処理
for item := range set.All() {
fmt.Println(item)
}
```

## 使用例

### 異なる型での使用

```go
// 文字列集合
fruits := hashset.NewFromSlice([]string{"apple", "banana", "orange"})

// 整数集合
numbers := hashset.NewFromSlice([]int{1, 2, 3, 4, 5})

// カスタム構造体(比較可能である必要があります)
type Person struct {
Name string
Age int
}

people := hashset.New[Person]()
people.Add(Person{Name: "Alice", Age: 30})
people.Add(Person{Name: "Bob", Age: 25})
```

### 共通要素の検索

```go
users1 := hashset.NewFromSlice([]string{"alice", "bob", "charlie"})
users2 := hashset.NewFromSlice([]string{"bob", "david", "eve"})
users3 := hashset.NewFromSlice([]string{"bob", "frank", "grace"})

// 3つすべての集合に共通するユーザーを検索
common := users1.Intersection(users2).Intersection(users3)
fmt.Println("共通ユーザー:", common.ToSlice()) // [bob]
```

### スライスから重複を除去

```go
func removeDuplicates[T comparable](slice []T) []T {
set := hashset.NewFromSlice(slice)
return set.ToSlice()
}

// 使用例
numbers := []int{1, 2, 2, 3, 3, 3, 4, 5}
unique := removeDuplicates(numbers)
// unique には [1, 2, 3, 4, 5] が含まれます(順序は保証されません)
```

### 集合ベースのデータ処理

```go
// ユーザー権限の処理
adminUsers := hashset.NewFromSlice([]string{"alice", "bob"})
activeUsers := hashset.NewFromSlice([]string{"alice", "charlie", "david"})
bannedUsers := hashset.NewFromSlice([]string{"eve", "frank"})

// アクティブな管理者ユーザーを検索
activeAdmins := adminUsers.Intersection(activeUsers)

// システムにアクセス可能なユーザーを検索(アクティブでかつ禁止されていない)
allowedUsers := activeUsers.Difference(bannedUsers)

// いずれかのカテゴリに言及されているすべてのユーザーを検索
allUsers := adminUsers.Union(activeUsers).Union(bannedUsers)
```

## スレッドセーフティ

この実装は**スレッドセーフではありません**。並行アクセスが必要な場合は、適切な同期処理でラップしてください:

### 例

```go
import "sync"

type SafeSet[T comparable] struct {
set hashset.Set[T]
mu sync.RWMutex
}

func NewSafeSet[T comparable]() *SafeSet[T] {
return &SafeSet[T]{
set: hashset.New[T](),
}
}

func (s *SafeSet[T]) Add(item T) {
s.mu.Lock()
defer s.mu.Unlock()
s.set.Add(item)
}

func (s *SafeSet[T]) Contains(item T) bool {
s.mu.RLock()
defer s.mu.RUnlock()
return s.set.Contains(item)
}
```