在Go中构造用户定义的地图

时间:2018-01-09 12:54:56

标签: dictionary go

我想创建一个地图,用于存储从一个点到另一个点的路线,它们之间的距离将用作地图中的值。

type Route struct {
    start  string
    finish string
}

m := make(map[Route]int)
v := Route{start: "A",
            finish: "B"}
m[v] = 42

从A到B的距离等于从B到A的距离。

w := Route{start: "B",
        finish: "A"}

如果再次将m[w]推入地图,我怎样才能获得m[w] = 42,因为vw是相同的路线。

P.S换句话说,当在地图中使用Route作为关键字时,当一个Route等于另一个Route时,是否可以覆盖规则?

3 个答案:

答案 0 :(得分:2)

map[Route]int定义为用户定义的类型,例如RouteDistance

type RouteDistance map[Route]int

然后在该类型上定义Find函数,以检查双向路由并返回距离。

func (rd RouteDistance) Find(r Route) (d int, ok bool) {
    routeDistance := map[Route]int(rd)
    d, ok = routeDistance[r]
    if ok {
        return
    }
    d, ok = routeDistance[Route{start: r.finish, finish: r.start}]
    if ok {
        return
    }
    return -1, false
}

仅使用单向路线和距离启动RouteDistance

rd := make(RouteDistance)
rd[Route{start: "A", finish: "B"}] = 42

获取路线的双向距离。

rd.Find(Route{start: "A", finish: "B"})
rd.Find(Route{start: "B", finish: "A"})

工作代码位于Playground

答案 1 :(得分:1)

使用Route为地图编制索引,其中finishstart互换:

m[Route{start: w.finish, finish: w.start}]

如果要检查两个方向,请为其创建辅助函数:

var m = make(map[Route]int)

func dist(r Route) int {
    if d, ok := m[r]; ok {
        return d
    }
    return m[Route{start: r.finish, finish: r.start}]
}

请注意,如果地图中没有方向,dist()将返回0。如果您也想要返回此信息:

func dist(r Route) (d int, found bool) {
    d, found = m[r]
    if !found {
        d, found = m[Route{start: r.finish, finish: r.start}]
    }
    return
}

Go Playground上尝试。

答案 2 :(得分:1)

有几种方法可以在不增加额外值的情况下执行此操作。执行两次地图访问:

r := Route{
    start: "B",
    finish: "A",
}
d, ok := m[r]
if !ok {
    r.start = "B"
    r.finish = "A"
    d, ok = m[r]
}
if !ok {
    // value not found
}

或者对于每个地图商店和访问权限,请对startfinish

进行排序
func Put(start, finish string, d int) {
    r := Route{start, finish}
    if start > finish {
        r.start = finish
        r.finish = start
    }
    m[r] = d
}

func Get(r Route) int {
    if r.start > r.finish {
        r.start, r.finish = r.finish, r.start
    }
    m[r] = d
}