tg-me.com/golang_for_two/52
Last Update:
Note #27 Evolution of reverse string "Hello, 世界"
4 года назад мне попался интересный вопрос: как же развернуть строку используя Го?! Сложность заключается в том, чтобы не сломать UTF-8 символы которые могут быть в строке. Т.е. если решать в лоб то получим: ��� ,olleH���
, а хотелось бы 界世 ,olleH
.
В 2009 Russ Cox в девелоперской рассылке golang-nuts [3] предложил решить эту задачку так:
func reverseString(s string) string {
n := 0
rune := make([]rune, len(s))
for _, r := range s {
rune[n] = r
n++
}
rune = rune[0:n]
// Reverse
for i := 0; i < n/2; i++ {
rune[i], rune[n-1-i] = rune[n-1-i], rune[i]
}
// Convert back to UTF-8.
return string(rune)
}
Немного громоздко, но все же работает и сейчас (оставил оригинальное решение, понятное дело, что можно улучшить, Russ писал думаю пару минут):
>> fmt.Println(reverseString("世Hello, 世"))
>> 世 ,olleH世
Если не много упростить, используя тот факт, что строку можно конвертировать на прямую в
[]rune
без дополнительного цикла [1]:func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
Идея та же, но код получился чуть более лаконичный.
Самое быстрое решение и не самое лаконичное:
func ReverseFast(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}
И самый интересный на мой взгляд вариант с помощью
defer
, рекомендую остановиться и подумать что же тут происходит на самом деле :func ReverseClosure(s string) (result string) {
for _, v := range s {
defer func(r rune) { result += string(r) }(v)
}
return
}
Это не самое быстрое решение, но оно показывает как используя замыкание мы сохраняем промежуточное значение в переменной
result
, для дальнейшего использования каждого defer вызова функции :)P.S. В качестве упражнения я рекомендую реализовать
func reverse(s string)
для так называемых “combining characters”. Те чтобы покрыть такой кейс:"as⃝df̅" превратить в "f̅ds⃝a"
Links:
[1] https://github.com/golang/example/blob/master/stringutil/reverse.go
[2] https://golang.org/pkg/unicode/utf8/#DecodeRuneInString
[3] https://groups.google.com/forum/#!topic/golang-nuts/oPuBaYJ17t4
[4] http://rosettacode.org/wiki/Reverse_a_string
BY 🇺🇦 Go for two :)
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/golang_for_two/52