web-dev-qa-db-ja.com

Golangでデータ構造を設定する

私は本当にgoogle golangが好きですが、標準ライブラリのセットなどの基本的なデータ構造を実装者が省略している理由を説明できる人がいますか?

69
cobie

この省略の潜在的な理由の1つは、マップを使用してセットをモデル化することが本当に簡単であることです。

正直なところ、それも少し見落としだと思いますが、Perlを見ると、まったく同じです。 Perlではリストとハッシュテーブルを取得し、Goでは配列、スライス、マップを取得します。 Perlでは通常、セットに関連するすべての問題に対してハッシュテーブルを使用しますが、Goにも同じことが当てはまります。

goでセットのintを模倣するために、マップを定義します。

set := make(map[int]bool)

何かを追加するのは簡単です:

i := valueToAdd()
set[i] = true

何かを削除するのは

delete(set, i)

そして、この構造の潜在的なぎこちなさは簡単に抽象化されます:

type IntSet struct {
    set map[int]bool
}

func (set *IntSet) Add(i int) bool {
    _, found := set.set[i]
    set.set[i] = true
    return !found   //False if it existed already
}

そして、削除と取得も同様に定義できます。完全な実装 here があります。ここでの主な欠点は、goにジェネリックがないことです。ただし、interface{}を使用してこれを行うことは可能です。その場合、getの結果をキャストします。

70
Daniel Gratzer

これは、シンプルさを重視するgolangに関係していると思います。 setsは、differenceintersectionunionissubsetなどのメソッドで本当に便利になります。おそらくgolangチームは、1つのデータ構造では多すぎると感じました。しかし、それ以外の場合、@ jozefgで説明されているように、addcontains、およびremoveのみを含む「ダムセット」は、mapを使用して簡単に複製できます。

3
Akavall

前の回答は、キーが組み込み型である場合にのみ機能します。前の答えを補足するために、要素がユーザー定義型であるセットを実装する方法を次に示します。

package math

// types

type IntPoint struct {
    X, Y int
}

// set implementation for small number of items
type IntPointSet struct {
    slice []IntPoint 
}

// functions

func (p1 IntPoint) Equals(p2 IntPoint) bool {
    return (p1.X == p2.X) && (p1.Y == p2.Y)
}

func (set *IntPointSet) Add(p IntPoint) {
    if ! set.Contains(p) {
        set.slice = append(set.slice, p)
    }
}

func (set IntPointSet) Contains(p IntPoint) bool {
  for _, v := range set.slice {
    if v.Equals(p) {
      return true
    }
  }
  return false
}

func (set IntPointSet) NumElements() int {
    return len(set.slice)
}

func NewIntPointSet() IntPointSet {
  return IntPointSet{(make([]IntPoint, 0, 10))}
}
2
amahfouz