如何在Go中定义一个集合的映射?

huangapple go评论87阅读模式
英文:

How to define a map of sets in Go?

问题

我想知道如何在Go语言中定义一个集合的映射。集合是一个无序唯一元素的集合。

这些集合是一个结构体(Tile)的集合。
映射的键是一个字符串。键是tile.X + "," + tile.Y的组合。

目前我有的代码只适用于一个元素,而不是一个集合。

type Tile struct {
    X int
    Y int
}

func (t Tile) GetKey() string {
    return strconv.Itoa(t.X) + "," + strconv.Itoa(t.Y)
}

// 这只适用于一个元素,而不是一个集合。
type Cache map[string]Tile
英文:

I would like to know how to define a map of sets in Go. A set is a collection of unordered unique elements.

The sets are collections of a struct (Tile).
The key of the map is a string. The key is the combination of tile.X + "," + tile.Y.

What I have so far. It only works for one element, not a set.

type Tile struct {
    X int
    Y int
}

func (t Tile) GetKey() {
    return strconv.Itoa(t.X) + "," + strconv.Itoa(t.Y)
}

// This only works for one element, not for a set.
type Cache map[string]Tile

答案1

得分: 1

如何表示一个集合

在Go语言中,集合通常使用从给定类型到定义其存在的原始值的映射来表示。map类型可以语义化地表示一个无序的唯一元素的集合。

var tileSet map[Tile]bool

请注意,你可以使用非指针的Tile结构作为映射的键,因为:

如果所有字段都是可比较的,那么结构值是可比较的。如果对应的非空字段相等,那么两个结构值是相等的。

显然,XY这两个int字段是可比较的。

这是如何使用这样的映射:

tileSet = make(map[Tile]bool, 0)

tile := Tile{X: 1, Y: 2}
tileSet[tile] = true

// 检查元素是否存在
if exists := tileSet[tile]; exists {
   // ...
}

// 遍历集合元素
for tile, _ := range tileSet {
   // ...
}

如何表示一个映射的集合

很简单:

var tileSetMap map[string]map[Tile]bool

为了简化代码,你还可以定义自己的集合类型:

type TileSet map[Tile]bool

然后可以这样使用:

func main() {
	var tileSetMap map[string]TileSet

	// 使用make正常初始化
	tileSetMap = make(map[string]TileSet, 0)
	tileSetMap["foo"] = make(TileSet, 0)

	tile := Tile{10, 20}
	tileSetMap["foo"][tile] = true
	
	fmt.Println(tileSetMap) // map[foo:map[{10 20}:true]]
}

Playground: https://play.golang.org/p/ObUo62SI3ih

[1] 规范:Map类型

键类型的操作数必须完全定义了相等运算符==和!=。

英文:

How to represent a set

Sets in Go are usually represented with maps from the given type to a primitive value that defines its existence. The map type is how you can semantically represent an unordered collection of unique elements.

var tileSet map[Tile]bool

Note that you can use non-pointer Tile structs as map keys. because:

> Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

...and clearly the two int fields X and Y are comparable.

This is how you use such a map:

tileSet = make(map[Tile]bool, 0)

tile := Tile{X:1,Y:2}
tileSet[tile] = true

// check existence
if exists := tileSet[tile]; exists {
   // ... 
}

// range over set elements
for tile, _ := range tileSet {
   // ...
}

How to represent a map of set

Trivially:

var tileSetMap map[string]map[Tile]bool

To simplify the code, you can also define your own set type:

type TileSet map[Tile]bool

and then

func main() {
	var tileSetMap map[string]TileSet

	// you initialize it normally with make
	tileSetMap = make(map[string]TileSet, 0)
	tileSetMap["foo"] = make(TileSet, 0)

	tile := Tile{10, 20}
	tileSetMap["foo"][tile] = true
	
	fmt.Println(tileSetMap) // map[foo:map[{10 20}:true]]
}

Playground: https://play.golang.org/p/ObUo62SI3ih

<hr>

[1] Specs: Map Types

> The comparison operators == and != must be fully defined for operands of the key type

huangapple
  • 本文由 发表于 2021年7月6日 17:32:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/68267991.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定