2011-01-16 6 views
3

Ich versuche, den integrierten Kartentyp als eine Reihe für einen eigenen Typ (Point, in diesem Fall) zu verwenden. Das Problem ist, wenn ich der Karte einen Punkt zuweise und später einen neuen, aber gleichen Punkt erzeuge und ihn als Schlüssel verwende, verhält sich die Karte so, als wäre dieser Schlüssel nicht in der Karte. Ist das nicht möglich?Go - Verwenden einer Karte für seine Set-Eigenschaften mit benutzerdefinierten Typen

// maptest.go 

package main 

import "fmt" 

func main() { 
    set := make(map[*Point]bool) 

    printSet(set) 
    set[NewPoint(0, 0)] = true 
    printSet(set) 
    set[NewPoint(0, 2)] = true 
    printSet(set) 

    _, ok := set[NewPoint(3, 3)] // not in map 
    if !ok { 
     fmt.Print("correct error code for non existent element\n") 
    } else { 
     fmt.Print("incorrect error code for non existent element\n") 
    } 

    c, ok := set[NewPoint(0, 2)] // another one just like it already in map 
    if ok { 
     fmt.Print("correct error code for existent element\n") // should get this 
    } else { 
     fmt.Print("incorrect error code for existent element\n") // get this 
    } 

    fmt.Printf("c: %t\n", c) 
} 

func printSet(stuff map[*Point]bool) { 
    fmt.Print("Set:\n") 
    for k, v := range stuff { 
     fmt.Printf("%s: %t\n", k, v) 
    } 
} 

type Point struct { 
    row int 
    col int 
} 

func NewPoint(r, c int) *Point { 
    return &Point{r, c} 
} 

func (p *Point) String() string { 
    return fmt.Sprintf("{%d, %d}", p.row, p.col) 
} 

func (p *Point) Eq(o *Point) bool { 
    return p.row == o.row && p.col == o.col 
} 

Antwort

2
package main 

import "fmt" 

type Point struct { 
    row int 
    col int 
} 

func main() { 
    p1 := &Point{1, 2} 
    p2 := &Point{1, 2} 
    fmt.Printf("p1: %p %v p2: %p %v\n", p1, *p1, p2, *p2) 

    s := make(map[*Point]bool) 
    s[p1] = true 
    s[p2] = true 
    fmt.Println("s:", s) 

    t := make(map[int64]*Point) 
t[int64(p1.row)<<32+int64(p1.col)] = p1 
t[int64(p2.row)<<32+int64(p2.col)] = p2 
    fmt.Println("t:", t) 
} 

Output: 
p1: 0x7fc1def5e040 {1 2} p2: 0x7fc1def5e0f8 {1 2} 
s: map[0x7fc1def5e0f8:true 0x7fc1def5e040:true] 
t: map[4294967298:0x7fc1def5e0f8] 

Wenn wir Zeiger auf zwei Pointsp1 und p2 mit den gleichen Koordinaten erstellen sie an unterschiedliche Adressen verweisen.

s := make(map[*Point]bool) erstellt eine Zuordnung, wobei der Schlüssel ein Zeiger auf den Speicher ist, der einem Point zugeordnet ist, und der Wert ist boolescher Wert. Wenn wir also die Elemente p1 und p2 der Karte s zuweisen, haben wir zwei verschiedene Map-Schlüssel und zwei verschiedene Map-Elemente mit denselben Koordinaten.

t := make(map[int64]*Point) erstellt eine Karte, wo der Schlüssel eine Zusammensetzung der Koordinaten von Point ist und der Wert ist ein Zeiger auf die Koordinaten Point. Wenn wir also die Elemente p1 und p2 der Karte t zuweisen, haben wir zwei gleiche Map-Schlüssel und ein Map-Element mit den gemeinsamen Koordinaten.

+1

Eine Alternative wäre 'map [int] map [int] Point'. Erhöhte Speicherverbrauch und Zugriffszeit, aber einfacher, ein Element zu finden. –

+0

Genau das, was ich sagen wollte. – crazy2be

+0

Ja. 'map [int] map [int] Punkt- und andere Schemata für die Map-Schlüssel, die sich auf den Wert der Punktkoordinaten anstatt auf einen Zeiger auf eine bestimmte Instanz eines Punktes stützen, funktionieren ebenfalls. – peterSO

Verwandte Themen