在Go语言中查找数组的模式

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

Pattern for lookup in Go array

问题

Go语言有方便的语法来定义数组查找表:

var myTable = [...]string{
  'a': "aaaa",
  'b': "bbbb",
  'z': "zoro",
}

在某些情况下(键在已知且范围不太大的情况下),这种方式比使用map创建表更高效。然而,使用map进行查找并判断键是否存在很容易。但是,要在这个数组中通过索引进行查找,我必须这样做:

if index < len(myTable) {
  if val := myTable[index]; val != "" {
    // 在这里,我知道索引存在于数组中,并且val是它的值
  }
}

是否有更简单/更常见的模式或库函数来实现这个功能?

英文:

Go has convenient syntax to define array lookup tables:

var myTable = [...]string{
  &#39;a&#39;: &quot;aaaa&quot;,
  &#39;b&#39;: &quot;bbbb&quot;,
  &#39;z&#39;: &quot;zoro&quot;,
}

In some cases (where keys are in known and not too big range) this is more efficient way to make table, than map. However, it is easy to make lookup in map and find if key not in it. But to do lookup by index in this array I have to do:

if index &lt; len(myTable) {
  if val := myTable[index]; val != &quot;&quot; {
    // here I know index exists in array and val is its value
  }
}

Is there simpler / more common pattern or library function to do this?

答案1

得分: 3

我不认为有任何特殊的内置语法可以消除这里对边界检查的需求。一种选择是将代码封装在一个自定义类型中。例如:

type StringTable []string

func (st StringTable) Get(i int) string {
    if i < 0 || i >= len(st) {
        return ""
    }
    return st[i]
}

您仍然可以使用相同的初始化语法来使用自定义类型:

myTable := StringTable{
    'a': "aaaa",
    'b': "bbbb",
    'z': "zoro",
}
fmt.Printf("%#v\n", myTable.Get('a'))
fmt.Printf("%#v\n", myTable.Get(-5))
fmt.Printf("%#v\n", myTable.Get('~')) // 大于 'z'

您可以在此处尝试这个示例:http://play.golang.org/p/nhti2dVE8B

英文:

I don't think there is any special builtin syntax to remove the need for a bounds check here. One option would be to wrap the code in a custom type. For example:

type StringTable []string

func (st StringTable) Get(i int) string {
	if i &lt; 0 || i &gt;= len(st) {
		return &quot;&quot;
	}
	return st[i]
}

You can still use the same initialiser syntax with the custom type:

myTable := StringTable{
	&#39;a&#39;: &quot;aaaa&quot;,
	&#39;b&#39;: &quot;bbbb&quot;,
	&#39;z&#39;: &quot;zoro&quot;,
}
fmt.Printf(&quot;%#v\n&quot;, myTable.Get(&#39;a&#39;))
fmt.Printf(&quot;%#v\n&quot;, myTable.Get(-5))
fmt.Printf(&quot;%#v\n&quot;, myTable.Get(&#39;~&#39;)) // greater than &#39;z&#39;

You can play around with this example here: http://play.golang.org/p/nhti2dVE8B

答案2

得分: 0

在某些情况下(其中键在已知且不太大的范围内),这是制作表格的更高效的方法,而不是使用映射。

是的。您希望将键转换为数组中的偏移量。然后,您可以在常数时间内进行查找。

假设您知道所有的键都将在集合A-Z中。因此,您创建一个包含26个条目的数组。当一个键进来时,您减去ASCII值“A”来获取您表格中的索引。嘭,常数时间的查找,这将比映射查找快得多。

请注意,您实际上并没有在任何地方存储键,它是隐含的。如果您想打印出您的表格,您需要自己生成所有的键(A-Z)。

英文:

> In some cases (where keys are in known and not too big range) this is more efficient way to make table, than map

Yes. You want to translate your key into an offset in the array. Then you can do the lookup in constant time.

Let's say you know all your keys will be in the set A-Z. So you create an array of 26 entries. When a key comes in, you subtract the ASCII value of "A" to get the index into your table. Boom, constant-time lookups, which will be much faster than a map lookup.

Note that you don't actually store the key anywhere, it's implicit. If you want to print out your table, you'd need to generate all keys (A-Z) yourself.

huangapple
  • 本文由 发表于 2014年3月24日 06:04:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/22597735.html
匿名

发表评论

匿名网友

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

确定