golang创建多级字符串映射

时间:2018-05-09 09:32:23

标签: dictionary go

我是Go语言的新手。我正在努力跟随用例。

我想在地图中存储会话ID(字符串)和reqeust No(字符串)以进行重复检查。当地图中没有条目时,它应该创建一个条目,否则它应该返回一个标记,表明条目已经存在。

var geocoder;
var map;

function initialize() {

  var center = new google.maps.LatLng(51.97559, 4.12565);
  map = new google.maps.Map(document.getElementById('map'), {
     center: center,
     zoom: 12,
     mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var bounds = new google.maps.LatLngBounds();

  var start = ['42.81405, 12.4886861111', '32.7994444444, 20.506775', '44.8062644989, 20.5005495758'];
  var end = ['47.81405, 18.4886861111', '33.7994444444, 21.506775', '39.8062644989, 16.5005495758'];

  var paths = [];

  for (var i=0; i < end.length; i++){
    var startCoords = start[i].split(",");
    var startPt = new google.maps.LatLng(startCoords[0],startCoords[1]);
    var endCoords = end[i].split(",");
    var endPt = new google.maps.LatLng(endCoords[0],endCoords[1]);
    paths.push([startPt, endPt]);

    bounds.extend(startPt);
    bounds.extend(endPt);
  }
  map.fitBounds(bounds);

  var polyline = new google.maps.Polygon({
    paths: paths,
    strokeColor: 'red',
    strokeWeight: 2,
    strokeOpacity: 1
  });

  polyline.setMap(map); 

}


google.maps.event.addDomListener(window, "load", initialize);

我面临的问题是每次调用函数时都会重写该值。 我在这里做错了什么?

3 个答案:

答案 0 :(得分:1)

如果给定会话ID的映射尚不存在,则只需创建内部映射(会话映射)的值(如果给定的请求编号不在其中,则 ),否则你清除之前存储的任何请求编号。

由于您使用bool作为内部映射(会话映射)的值类型,您可以利用它来编写更简单的代码(使用不在其中的键索引映射将产生零值值类型,false类型的bool,正确告知密钥不在其中):

func chkDuplicate(m map[string]map[string]bool, sess string, Reqno string) bool {
    sessMap := m[sess]
    if sessMap == nil {
        m[sess] = map[string]bool{Reqno: true}
        return false
    }

    if sessMap[Reqno] {
        return true
    }
    sessMap[Reqno] = true
    return false
}

测试它:

func main() {
    mySessionData := make(map[string]map[string]bool)

    for _, reqNo := range []string{"1", "2", "3", "2", "4"} {
        ret := chkDuplicate(mySessionData, "session1", reqNo)
        fmt.Println(ret, mySessionData)
    }

    delete(mySessionData, "session1")
    fmt.Println(mySessionData)
}

输出(在Go Playground上尝试):

false map[session1:map[1:true]]
false map[session1:map[1:true 2:true]]
false map[session1:map[1:true 2:true 3:true]]
true map[session1:map[2:true 3:true 1:true]]
false map[session1:map[2:true 3:true 4:true 1:true]]
map[]

请注意bool - 尽管可能很小 - 确实需要内存。由于我们可以查询键是否在映射中,因此我们可以选择使用不需要内存的值类型,例如空结构(struct{})。有了它,它可能看起来像这样:

func chkDuplicate(m map[string]map[string]struct{}, sess string, Reqno string) bool {
    sessMap := m[sess]
    if sessMap == nil {
        m[sess] = map[string]struct{}{Reqno: struct{}{}}
        return false
    }

    if _, ok := sessMap[Reqno]; ok {
        return true
    }
    sessMap[Reqno] = struct{}{}
    return false
}

测试和结果(几乎)相同,在Go Playground上尝试。

警告:从示例中可以看出,您希望使用它来跟踪先前是否已提供(Web)请求,其中通常涉及多个goroutine。此解决方案对于并发使用不安全

答案 1 :(得分:0)

sess变量总是等于session1,因此您只需覆盖关键session1的值。你必须有无法区分的密钥。

如果您只想检查重复项,请执行以下操作:

package main 

import "fmt"

func main() {
    mySessionData := make(map[string]bool)

    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session2", "1")
    fmt.Println(mySessionData) # two keys printed
}

func chkDuplicate(m map[string]bool, sess string, Reqno string) bool {
    key := fmt.Sprintf("%s-%s", sess, Reqno)
    _, found := m[key]
    if !found {
       m[key] = true    
    }
   return !found
}

答案 2 :(得分:0)

使用结构键而不是多级地图通常更简单: https://play.golang.org/p/WFlGi1rrVOm