Доступ к случайному руническому элементу строки без использования for ... range
Я недавно задал этот вопрос, и ответы расширили мое понимание, но они не решили реальную проблему, которая у меня была. Итак, я постараюсь задать похожий, но другой вопрос следующим образом.
Предположим, что я хочу получить доступ к случайным rune
элемент string
, Одним из способов является:
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
}
Что если я хочу вызывать такую функцию много раз? Я думаю, что я ищу, это как оператор / функция, как str[i]
(который возвращает byte
) которые возвращают rune
элемент в i
Позиция Почему к этому элементу можно получить доступ, используя for ... range
но не через финтон как str.At(i)
например?
1 ответ
string
значения в Go хранят последовательность байтов текста в кодировке UTF-8. Это дизайнерское решение, которое было принято, и оно не изменится.
Если вы хотите эффективно получить rune
из него по произвольному индексу, вы должны декодировать байты, вы ничего не можете с этим поделать (for ... range
делает это декодирование). Там нет "ярлык". Выбранное представление просто не предоставляет этого из коробки.
Если вам приходится делать это часто / много раз, вы должны изменить свой ввод и не использовать string
но []rune
, поскольку это фрагмент и может быть эффективно проиндексирован. string
в го нет []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]
}
Зависит от случая, стоит ли это того: RuneAt()
называется с небольшим набором string
s, это может значительно улучшить производительность. Если переданные строки более или менее уникальны, это приведет к снижению производительности и большому использованию памяти. Также эта реализация не является безопасной для одновременного использования.