Поскольку число выживших рун меньше utf8.RuneSelf , эту проблему можно решить, работая с байтами.Если какой-либо байт находится не в [^a-zA-Z0-9 ]
, то этот байт является частью руны, которую необходимо удалить.
func strip(s string) string {
var result strings.Builder
for i := 0; i < len(s); i++ {
b := s[i]
if ('a' <= b && b <= 'z') ||
('A' <= b && b <= 'Z') ||
('0' <= b && b <= '9') ||
b == ' ' {
result.WriteByte(b)
}
}
return result.String()
}
Разновидностью этой функции является предварительное распределение результата путем вызова result.Grow:
func strip(s string) string {
var result strings.Builder
result.Grow(len(s))
...
Это гарантирует, что функция выполняет одно выделение памяти, но это выделение памяти может бытьзначительно больше необходимого, если отношение выживших рун к исходным рунам низкое.
Функция strip
в этом ответе написана для работы с string
аргументами и типами результатов, потому что это типы, используемые ввопрос.
Если приложение работает с исходным текстом []byte
и этот исходный текст можно изменить, то будет эффективнее обновить []byte
на месте.Для этого скопируйте выживающие байты в начало среза и обновите его, когда закончите.Это позволяет избежать выделения памяти и накладных расходов в строках.Это изменение аналогично ответу peterSO на этот вопрос.
func strip(s []byte) []byte {
n := 0
for _, b := range s {
if ('a' <= b && b <= 'z') ||
('A' <= b && b <= 'Z') ||
('0' <= b && b <= '9') ||
b == ' ' {
s[n] = b
n++
}
}
return s[:n]
}
В зависимости от фактических данных один из подходов в этом ответе может быть быстрее, чем подходы в вопросе.