답변:
Go1에서 룬은 내장 유형입니다.
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
Golang-nuts 메일 링리스트에있는 Russ Cox 는
package main
import "fmt"
func main() {
input := "The quick brown 狐 jumped over the lazy 犬"
// Get Unicode code points.
n := 0
rune := make([]rune, len(input))
for _, r := range input {
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.
output := string(rune)
fmt.Println(output)
}
rune:=[]rune(input)
.
이것은 기능에 대한 모든 비웃음없이 작동합니다.
func Reverse(s string) (result string) {
for _,v := range s {
result = string(v) + result
}
return
}
이것은 두 가지를 고려하여 유니 코드 문자열에서 작동합니다.
그래서 여기에 간다 :
func reverse(s string) string {
o := make([]int, utf8.RuneCountInString(s));
i := len(o);
for _, c := range s {
i--;
o[i] = c;
}
return string(o);
}
i:=len(o)-1
for를 할당 한 다음 한 줄로 접습니다 for _, c:=range s { o[i--]=c; }
. Man I HATE for without 괄호-이것이 허용 for(_, c:=range s) { o[i--]=c; }
에서 golang / 예 / stringutil / reverse.go : 이동 예제 프로젝트 , 앤드류 Gerrand에 의해
/*
Copyright 2014 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Reverse returns its argument string reversed rune-wise left to right.
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)
}
문자열 "bròwn"을 뒤집은 후 올바른 결과는 "nẁorb"가 아니라 "nwòrb"여야합니다.
문자 o 위의 무덤에 유의하십시오.
"as⃝df̅"와 역방향 결과 "f̅ds⃝a"와 같은 유니 코드 결합 문자를 보존
하려면 아래 나열된 다른 코드를 참조하십시오.
나는 Simon 이 그의 솔루션 을 게시 했을 때이 질문을 발견했습니다. 문자열은 불변하기 때문에 매우 비효율적입니다. 다른 제안 된 솔루션도 결함이 있습니다. 작동하지 않거나 비효율적입니다.
다음은 문자열이 유효한 UTF-8이 아니거나 문자열에 결합 문자가 포함 된 경우를 제외하고 작동하는 효율적인 솔루션입니다.
package main
import "fmt"
func Reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}
func main() {
fmt.Println(Reverse(Reverse("Hello, 世界")))
fmt.Println(Reverse(Reverse("The quick brown 狐 jumped over the lazy 犬")))
}
return string(runes)
모든 경우에 적용되는 것은 아닙니다.
여기에 너무 많은 답변이 있습니다. 그들 중 일부는 명확한 중복입니다. 그러나 왼쪽 에서조차 최상의 솔루션을 선택하기가 어렵습니다.
그래서 나는 답변을 살펴보고 유니 코드에서 작동하지 않는 것을 버리고 중복을 제거했습니다. 가장 빠른 것을 찾기 위해 생존자를 벤치마킹했습니다. 따라서 다음은 어트 리뷰 션을 사용한 결과 입니다 (내가 놓친 답변을 발견했지만 추가 할 가치가있는 경우 벤치 마크를 자유롭게 수정하십시오).
Benchmark_rmuller-4 100000 19246 ns/op
Benchmark_peterSO-4 50000 28068 ns/op
Benchmark_russ-4 50000 30007 ns/op
Benchmark_ivan-4 50000 33694 ns/op
Benchmark_yazu-4 50000 33372 ns/op
Benchmark_yuku-4 50000 37556 ns/op
Benchmark_simon-4 3000 426201 ns/op
따라서 rmuller 의 가장 빠른 방법은 다음과 같습니다.
func Reverse(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)
}
어떤 이유로 벤치 마크를 추가 할 수 없기 때문에 복사 PlayGround할 수 있습니다 (여기서 테스트를 실행할 수 없습니다). 이름을 바꾸고 실행하십시오.go test -bench=.
Reverse
UTF8 인코딩과 결합 된 문자를 존중 하는 다음 함수를 작성했습니다 .
// Reverse reverses the input while respecting UTF8 encoding and combined characters
func Reverse(text string) string {
textRunes := []rune(text)
textRunesLength := len(textRunes)
if textRunesLength <= 1 {
return text
}
i, j := 0, 0
for i < textRunesLength && j < textRunesLength {
j = i + 1
for j < textRunesLength && isMark(textRunes[j]) {
j++
}
if isMark(textRunes[j-1]) {
// Reverses Combined Characters
reverse(textRunes[i:j], j-i)
}
i = j
}
// Reverses the entire array
reverse(textRunes, textRunesLength)
return string(textRunes)
}
func reverse(runes []rune, length int) {
for i, j := 0, length-1; i < length/2; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
}
// isMark determines whether the rune is a marker
func isMark(r rune) bool {
return unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r) || unicode.Is(unicode.Mc, r)
}
최대한 효율적이고 읽기 쉽게 만들기 위해 최선을 다했습니다. 아이디어는 간단합니다. 룬을 가로 질러 결합 된 캐릭터를 찾은 다음 결합 된 캐릭터의 룬을 제자리에서 뒤집습니다. 모두 덮었 으면 전체 문자열의 룬도 제자리에서 뒤집습니다.
이 문자열을 뒤집고 싶습니다 bròwn
. 는 ò
두 룬의 하나에 의해 표현되는 o
이 유니 하나 \u0301a
은 "죽음"을 나타낸다.
간단히하기 위해 다음과 같은 문자열을 표현해 보겠습니다 bro'wn
. 가장 먼저 할 일은 결합 된 문자를 찾아 뒤집는 것입니다. 이제 우리는 문자열 br'own
. 마지막으로 전체 문자열을 뒤집고 nwo'rb
. 이것은 우리에게 다음과 같이 반환됩니다.nwòrb
사용하려면 https://github.com/shomali11/util에서 찾을 수 있습니다 .
다음은 몇 가지 다른 시나리오를 보여주는 몇 가지 테스트 사례입니다.
func TestReverse(t *testing.T) {
assert.Equal(t, Reverse(""), "")
assert.Equal(t, Reverse("X"), "X")
assert.Equal(t, Reverse("b\u0301"), "b\u0301")
assert.Equal(t, Reverse("😎⚽"), "⚽😎")
assert.Equal(t, Reverse("Les Mise\u0301rables"), "selbare\u0301siM seL")
assert.Equal(t, Reverse("ab\u0301cde"), "edcb\u0301a")
assert.Equal(t, Reverse("This `\xc5` is an invalid UTF8 character"), "retcarahc 8FTU dilavni na si `�` sihT")
assert.Equal(t, Reverse("The quick bròwn 狐 jumped over the lazy 犬"), "犬 yzal eht revo depmuj 狐 nwòrb kciuq ehT")
}
Stephan202의 원래 제안을 기반으로하고 유니 코드 문자열에서 작동하는 것으로 보입니다.
import "strings";
func Reverse( orig string ) string {
var c []string = strings.Split( orig, "", 0 );
for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 {
c[i], c[j] = c[j], c[i]
}
return strings.Join( c, "" );
}
대체, 문자열 패키지를 사용하지 않지만 '유니 코드 안전'은 사용하지 않습니다.
func Reverse( s string ) string {
b := make([]byte, len(s));
var j int = len(s) - 1;
for i := 0; i <= j; i++ {
b[j-i] = s[i]
}
return string ( b );
}
//Reverse reverses string using strings.Builder. It's about 3 times faster
//than the one with using a string concatenation
func Reverse(in string) string {
var sb strings.Builder
runes := []rune(in)
for i := len(runes) - 1; 0 <= i; i-- {
sb.WriteRune(runes[i])
}
return sb.String()
}
//Reverse reverses string using string
func Reverse(in string) (out string) {
for _, r := range in {
out = string(r) + out
}
return
}
BenchmarkReverseStringConcatenation-8 1000000 1571 ns/op 176 B/op 29 allocs/op
BenchmarkReverseStringsBuilder-8 3000000 499 ns/op 56 B/op 6 allocs/op
strings.Builder 사용은 문자열 연결을 사용하는 것보다 약 3 배 빠릅니다.
다음은 상당히 다릅니다. 다른 답변에는 나열되지 않은 더 기능적인 접근 방식을 말합니다.
func reverse(s string) (ret string) {
for _, v := range s {
defer func(r rune) { ret += string(r) }(v)
}
return
}
ret
, 각 지연 함수에 의해 추가 처리를 위해 반환 변수 가 어떻게 닫혀 있는지 보여줍니다 .
이것은 가장 빠른 구현입니다
func Reverse(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)
}
const (
s = "The quick brown 狐 jumped over the lazy 犬"
reverse = "犬 yzal eht revo depmuj 狐 nworb kciuq ehT"
)
func TestReverse(t *testing.T) {
if Reverse(s) != reverse {
t.Error(s)
}
}
func BenchmarkReverse(b *testing.B) {
for i := 0; i < b.N; i++ {
Reverse(s)
}
}
이 코드는 문자 결합 시퀀스를 그대로 유지하며 잘못된 UTF-8 입력에서도 작동해야합니다.
package stringutil
import "code.google.com/p/go.text/unicode/norm"
func Reverse(s string) string {
bound := make([]int, 0, len(s) + 1)
var iter norm.Iter
iter.InitString(norm.NFD, s)
bound = append(bound, 0)
for !iter.Done() {
iter.Next()
bound = append(bound, iter.Pos())
}
bound = append(bound, len(s))
out := make([]byte, 0, len(s))
for i := len(bound) - 2; i >= 0; i-- {
out = append(out, s[bound[i]:bound[i+1]]...)
}
return string(out)
}
유니 코드 / 노름 프리미티브가 할당하지 않고 문자열의 경계를 통해 반복 할 수 있도록 허용한다면 좀 더 효율적일 수 있습니다. https://code.google.com/p/go/issues/detail?id=9055 도 참조하세요 .
[]byte
까지 string
이동 유효한 코드 포인트로 "잘못된 UTF-8 입력을"대체합니다 \uFFFD
.
string
. Go에 잘못된 UTF-8이 존재하지 않는다는 뜻입니다. 그러나 []byte
.
자소 클러스터를 처리해야하는 경우 unicode 또는 regexp 모듈을 사용하십시오.
package main
import (
"unicode"
"regexp"
)
func main() {
str := "\u0308" + "a\u0308" + "o\u0308" + "u\u0308"
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme(str))
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme2(str))
}
func ReverseGrapheme(str string) string {
buf := []rune("")
checked := false
index := 0
ret := ""
for _, c := range str {
if !unicode.Is(unicode.M, c) {
if len(buf) > 0 {
ret = string(buf) + ret
}
buf = buf[:0]
buf = append(buf, c)
if checked == false {
checked = true
}
} else if checked == false {
ret = string(append([]rune(""), c)) + ret
} else {
buf = append(buf, c)
}
index += 1
}
return string(buf) + ret
}
func ReverseGrapheme2(str string) string {
re := regexp.MustCompile("\\PM\\pM*|.")
slice := re.FindAllString(str, -1)
length := len(slice)
ret := ""
for i := 0; i < length; i += 1 {
ret += slice[length-1-i]
}
return ret
}
str
출력 인용은 최고의 견적을 수정합니다!
기존 구현을 가져올 수도 있습니다.
import "4d63.com/strrev"
그때:
strrev.Reverse("abåd") // returns "dåba"
또는 유니 코드 조합 문자를 포함하는 문자열을 반전하려면 :
strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"
이러한 구현은 유니 코드 멀티 바이트의 올바른 순서 지정 및 반전시 문자 결합을 지원합니다.
참고 : 많은 프로그래밍 언어에서 내장 된 문자열 역방향 함수는 결합을 유지하지 않으며 결합 문자를 식별하는 데 훨씬 더 많은 실행 시간이 필요합니다.
다음 두 가지 방법 은 문자 결합을 보존 하는 가장 빠른 솔루션 보다 더 빠르게 실행 되지만 벤치 마크 설정에서 뭔가 빠졌다는 의미는 아닙니다.
//input string s
bs := []byte(s)
var rs string
for len(bs) > 0 {
r, size := utf8.DecodeLastRune(bs)
rs += fmt.Sprintf("%c", r)
bs = bs[:len(bs)-size]
} // rs has reversed string
이것에서 영감을 얻은 두 번째 방법
//input string s
bs := []byte(s)
cs := make([]byte, len(bs))
b1 := 0
for len(bs) > 0 {
r, size := utf8.DecodeLastRune(bs)
d := make([]byte, size)
_ = utf8.EncodeRune(d, r)
b1 += copy(cs[b1:], d)
bs = bs[:len(bs) - size]
} // cs has reversed bytes
참고 : 이 답변은 2009 년의 것이므로 지금까지 더 나은 솔루션이있을 것입니다.
약간 '라운드 어바웃'처럼 보이며 아마도 그다지 효율적이지는 않지만 Reader 인터페이스를 사용하여 문자열을 읽는 방법을 보여줍니다. IntVector는 utf8 문자열로 작업 할 때 버퍼로도 매우 적합 해 보입니다.
'크기'부분을 생략하고 Insert로 벡터에 삽입하면 더 짧을 것 같지만, 새 룬이 추가 될 때마다 전체 벡터를 한 번 뒤로 밀어야하므로 효율성이 떨어질 것 같습니다. .
이 솔루션은 확실히 utf8 문자로 작동합니다.
package main
import "container/vector";
import "fmt";
import "utf8";
import "bytes";
import "bufio";
func
main() {
toReverse := "Smørrebrød";
fmt.Println(toReverse);
fmt.Println(reverse(toReverse));
}
func
reverse(str string) string {
size := utf8.RuneCountInString(str);
output := vector.NewIntVector(size);
input := bufio.NewReader(bytes.NewBufferString(str));
for i := 1; i <= size; i++ {
rune, _, _ := input.ReadRune();
output.Set(size - i, rune);
}
return string(output.Data());
}
유니 코드에서 작동하는 버전입니다. utf8.Rune 함수를 기반으로합니다.
func Reverse(s string) string {
b := make([]byte, len(s));
for i, j := len(s)-1, 0; i >= 0; i-- {
if utf8.RuneStart(s[i]) {
rune, size := utf8.DecodeRuneInString(s[i:len(s)]);
utf8.EncodeRune(rune, b[j:j+size]);
j += size;
}
}
return string(b);
}
룬은 유형이므로 사용하십시오. 또한 Go는 세미콜론을 사용하지 않습니다.
func reverse(s string) string {
l := len(s)
m := make([]rune, l)
for _, c := range s {
l--
m[l] = c
}
return string(m)
}
func main() {
str := "the quick brown 狐 jumped over the lazy 犬"
fmt.Printf("reverse(%s): [%s]\n", str, reverse(str))
}
아래 코드를 시도하십시오.
package main
import "fmt"
func reverse(s string) string {
chars := []rune(s)
for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
chars[i], chars[j] = chars[j], chars[i]
}
return string(chars)
}
func main() {
fmt.Printf("%v\n", reverse("abcdefg"))
}
자세한 내용은 http://golangcookbook.com/chapters/strings/reverse/
및 http://www.dotnetperls.com/reverse-string-go를 확인 하세요.
간단한 문자열의 경우 다음과 같은 구성을 사용할 수 있습니다.
func Reverse(str string) string {
if str != "" {
return Reverse(str[1:]) + str[:1]
}
return ""
}
또 다른 솔루션 (tm) :
package main
import "fmt"
type Runes []rune
func (s Runes) Reverse() (cp Runes) {
l := len(s); cp = make(Runes, l)
// i <= 1/2 otherwise it will mess up with odd length strings
for i := 0; i <= l/2; i++ {
cp[i], cp[l-1-i] = s[l-1-i], s[i]
}
return cp
}
func (s Runes) String() string {
return string(s)
}
func main() {
input := "The quick brown 狐 jumped over the lazy 犬 +odd"
r := Runes(input)
output := r.Reverse()
valid := string(output.Reverse()) == input
fmt.Println(len(r), len(output), r, output.Reverse(), valid)
}
package reverseString
import "strings"
// ReverseString - output the reverse string of a given string s
func ReverseString(s string) string {
strLen := len(s)
// The reverse of a empty string is a empty string
if strLen == 0 {
return s
}
// Same above
if strLen == 1 {
return s
}
// Convert s into unicode points
r := []rune(s)
// Last index
rLen := len(r) - 1
// String new home
rev := []string{}
for i := rLen; i >= 0; i-- {
rev = append(rev, string(r[i]))
}
return strings.Join(rev, "")
}
테스트
package reverseString
import (
"fmt"
"strings"
"testing"
)
func TestReverseString(t *testing.T) {
s := "GO je úžasné!"
r := ReverseString(s)
fmt.Printf("Input: %s\nOutput: %s", s, r)
revR := ReverseString(r)
if strings.Compare(s, revR) != 0 {
t.Errorf("Expecting: %s\n. Got: %s\n", s, revR)
}
}
산출
Input: GO je úžasné!
Output: !énsažú ej OG
PASS
ok github.com/alesr/reverse-string 0.098s
a+´
은á
. 나는 그것을 정규화하지 않고 어떻게 고려할 수 있는지 궁금합니다.