从Go中获取数组/切片中的元素索引或地图中的键值?

时间:2015-08-11 23:47:08

标签: go

我有一个枚举的字符串列表(它们是常量,例如国家列表),我希望能够在提供枚举的int值时获取字符串,反之亦然能够在提供字符串时获取枚举的int值。这是为了在数据库事务之间进行转换。

var MyData = [...]string {
  "string1", // index 0
  "string2", // index 1
  "string3", // index 2  
}

对于像python这样的语言来说很简单,人们可以像MyData [1]那样去做" string2"和MyData.index(" string2")得到1。

一些可能的解决方案是

  • 编写我自己的函数,通过迭代数组/切片来获取索引
  • 对数组/切片进行排序,并使用搜索功能返回索引(虽然这不允许排序,这是我最喜欢的顺序)
  • 维护一个映射和一个相互镜像的数组,这很容易出错。

说到地图,可以访问特定值的键吗?然后我可以简单地得到如下的地图,并且在提供int值时能够获取字符串键。 / p>

var MyData = map[string]int {
  "string1": 0,
  "string2": 1,
  "string3": 2,
}

更新:在接受我的回答之前,我想更彻底地解释这个问题,我知道这个问题必须相当普遍。我基本上有一组不变的字符串(例如国家列表),每个字符串都有一个相关的整数值。在我的数据库中,我只是存储整数以节省空间,因为有数百万条目。但是当我从数据库中显示一个条目时,我需要显示字符串值,使其对用户可读。一个简单的数组就可以做到这一点。但是,我还需要向数据库添加条目(例如新人及其居住国),并且在此方案中需要将从表单中输入的国家/地区字符串转换为该整数值。同样,这只是一个示例用例,但目标保持不变。我需要一个可以在字符串值和枚举的int值之间双向转换的表。最明显的做法是维护一个数组(用于int到字符串的转换)和一个map(用于字符串)到int翻译)。我不想手动维护这两个变量,因为这很容易出错。所以我的解决方案是只维护一个数组,并让构造函数方法在程序首次运行时自动在运行时构建映射。这样做的好处是,当我根据字符串获取整数值时,不需要遍历整个数组(这是另一个提议的解决方案)。

3 个答案:

答案 0 :(得分:3)

在这两种情况下,您都应该使用内置范围功能。

for k, v := range MyData {
}


for i, v := range ThisArray {
}


for i, _ := range ThisArrayIndexOnly {
    value := ThisArrayIndexOnly[i]
}

您可以在此基础上构建辅助函数或任何您喜欢的函数,但range基本上是可用于访问该数据的机制。如果你想要一个“indexof”函数,它将是

for i, v := range ArrayPassedIntoFunction {
     if v == ValuePassedIntoFunction {
          return i
     }
}
return -1

要获得该值,您当然会执行MyArray[i]包括边界检查或其他任何内容。请注意,上面的伪代码是用一种表示它是数组的样式编写的,但实际上相同的代码适用于地图,我通常只使用var名称k而不是i

答案 1 :(得分:2)

假设您想要获取数组数据

中的单词索引
data := [...] {"one","two","three"}

或固定长度数组

data := [3] {"one","two","three"}

创建功能

func indexOf(word string, data []string) (int) {
    for k, v := range data {
        if word == v {
            return k
        }
    }
    return -1
}

从上面的函数中获取值,以匹配类型,将数组传递给array[:],如下所示

fmt.Println(indexOf("two", data[:]))

答案 2 :(得分:0)

这是我之前提到的解决方案,它适用于静态切片(这是我的用例)。每次我想要值的索引时迭代切片会增加不必要的延迟,特别是因为我的数据在运行时是静态的。这只是创建一个初始化切片并创建相应逆映射的结构。然后我将使用GetKey和GetVal方法通过提供int'值'来获取字符串'key',或者通过提供字符串'key'来获取int'值'。也许已经有办法在Go中获取地图特定值的关键字。

type MyData struct {
    dataslice []string
    datamap map[string]int
}

func NewMyData() *MyData {
    m := new(MyData)
    m.dataslice= []string {
        "string1",
        "string2",
        "string3",
    }
    m.datamap = make(map[string]int)
    for x := range m.dataslice {
        m.datamap[m.dataslice[x]] = x
    }
    return m
}

func (m *MyData) GetKey(x int) string {
    return m.dataslice[x]
}

func (m *MyData) GetVal(x string) int {
    return m.datamap[x]
}