在不使用 for ... range 的情况下访问字符串的随机符文元素
Access random rune element of string without using for ... range
我最近问了 问题,答案增加了我的理解,但它们并没有解决我遇到的实际问题。因此,我将尝试提出一个类似但不同的问题如下。
假设我想访问 string
的随机 rune
元素。一种方式是:
func RuneElement(str string, idx int) rune {
var ret rune
for i, c := range str {
if i == idx {
return c
}
}
return ret // out of range -> proper handling is needed
}
如果我想多次调用这样的函数怎么办?我想我正在寻找的是 operator/function 之类的 str[i]
(return 是 byte
),return rune
元素位于 i
-第个位置。为什么可以使用 for ... range
而不是通过 str.At(i)
之类的函数访问此元素?
Go 中的 string
值存储文本的 UTF-8 编码字节序列。这是已经做出的设计决定,不会改变。
如果你想在任意索引处有效地从中获取 rune
,你必须解码字节,对此你无能为力(for ... range
进行解码) .没有"shortcut"。所选择的表示形式并没有提供开箱即用的功能。
如果您必须经常/多次执行此操作,您应该更改您的输入而不是使用 string
,而是使用 []rune
,因为它是一个切片并且可以被有效地索引。 string
在 Go 中不是 []rune
。 string
在 Go 中实际上是只读的 []byte
(UTF-8)。期间.
如果您无法更改输入类型,您可以构建一个从 string
映射到其 []rune
的内部缓存:
var cache = map[string][]rune{}
func RuneAt(s string, idx int) rune {
rs := cache[s]
if rs == nil {
rs = []rune(s)
cache[s] = []rune(s)
}
if idx >= len(rs) {
return 0
}
return rs[idx]
}
这是否值得取决于具体情况:如果使用一小组 string
调用 RuneAt()
,这可能会大大提高性能。如果传递的字符串或多或少是唯一的,这将导致性能下降和大量内存使用。此实现对于并发使用也不安全。
我最近问了
假设我想访问 string
的随机 rune
元素。一种方式是:
func RuneElement(str string, idx int) rune {
var ret rune
for i, c := range str {
if i == idx {
return c
}
}
return ret // out of range -> proper handling is needed
}
如果我想多次调用这样的函数怎么办?我想我正在寻找的是 operator/function 之类的 str[i]
(return 是 byte
),return rune
元素位于 i
-第个位置。为什么可以使用 for ... range
而不是通过 str.At(i)
之类的函数访问此元素?
string
值存储文本的 UTF-8 编码字节序列。这是已经做出的设计决定,不会改变。
如果你想在任意索引处有效地从中获取 rune
,你必须解码字节,对此你无能为力(for ... range
进行解码) .没有"shortcut"。所选择的表示形式并没有提供开箱即用的功能。
如果您必须经常/多次执行此操作,您应该更改您的输入而不是使用 string
,而是使用 []rune
,因为它是一个切片并且可以被有效地索引。 string
在 Go 中不是 []rune
。 string
在 Go 中实际上是只读的 []byte
(UTF-8)。期间.
如果您无法更改输入类型,您可以构建一个从 string
映射到其 []rune
的内部缓存:
var cache = map[string][]rune{}
func RuneAt(s string, idx int) rune {
rs := cache[s]
if rs == nil {
rs = []rune(s)
cache[s] = []rune(s)
}
if idx >= len(rs) {
return 0
}
return rs[idx]
}
这是否值得取决于具体情况:如果使用一小组 string
调用 RuneAt()
,这可能会大大提高性能。如果传递的字符串或多或少是唯一的,这将导致性能下降和大量内存使用。此实现对于并发使用也不安全。