Доступ к случайному руническому элементу строки без использования 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() называется с небольшим набором strings, это может значительно улучшить производительность. Если переданные строки более или менее уникальны, это приведет к снижению производительности и большому использованию памяти. Также эта реализация не является безопасной для одновременного использования.

Другие вопросы по тегам