Go에서 문자열을 뒤집는 방법?


답변:


94

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)
}

4
Go에서 len ()을 사용하여 문자열 / 배열 / 슬라이스 등의 길이를 알아낼 수 없습니다. 그 이유는 무엇입니까? -Go의 len ()은 입력 크기 (바이트)를 의미합니다. 길이와 일치하지 않습니다. -모든 utf8의 룬이 같은 크기는 아닙니다. 1, 2, 4 또는 8이 될 수 있습니다.-룬의 길이를 얻으려면 unicode / ut8 패키지의 메서드 RuneCountInString을 사용해야합니다.
Anvesh Checka 2014 년

15
@AnveshChecka, 틀 렸습니다. golang.org/pkg/builtin/#len을 참조하세요 . 슬라이스의 len ()은 바이트 단위의 크기가 아닌 요소의 수를 확실히 반환합니다. 룬 조각이 올바른 방법입니다.
chowey

3
@ рытфолд 문자 결합에는 사용할 수 없습니다. play.golang.org/p/sBgZAV7gCb를 참조하십시오 . 결합 문자는 기본 문자로 교체되지 않습니다.
chowey

53

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)
}

20
나는 그들이 인코딩에 대해 생각하도록 강요하는 방식을 좋아합니다.
György Andrasek

10
주제에서 벗어난 : 왜 [go-nuts]가 아닌 [golang-nuts]입니까?
Jimmy

2
와우, 후진 할 때 이중 할당이 가능합니까? 흥미 롭군. 이제 룬 수가 고르지 않은 문자열을 생각해보십시오. 중간은 특별한 대우를받으며 결국 정확한 최종 결과를 얻습니다. :) 내가 당장 생각하지 못했을 흥미로운 작은 최적화.
Kissaki

4
이 변환이 룬으로 변환되는 이유를 이해할 수 없습니다 rune:=[]rune(input).
siritinga

1
첫 번째 for 범위 루프는 필요하지 않습니다. 출력 : = [] rune (input); N : = LEN (출력) 그리고 당신은 룬 = 룬에게 필요하지 않습니다 [0 : N을]
dvallejo

29

이것은 기능에 대한 모든 비웃음없이 작동합니다.

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}

6
작동하는 동안 문자열은 불변이므로 매우 비효율적입니다. 더 효율적인 솔루션을 게시했습니다.
peterSO

5
이다 훨씬 너무 쉽게 이해하기. 확인 어렵게 :-) (그리고, "플러스 하나"단지 그것에서 얻기를위한)
Roboprog

2
역전 문자열이 병목 현상이 아닌 한 이것이 최선의 대답입니다.
Banjocat 2015-06-15

1
@dolmen-왜 이것이 문자 결합을 처리하지 않습니까? 문자열의 범위는 코드 포인트 인 룬을 반환합니다.
Stan R.

1
@StanR. 룬은 문양이 아닙니다. 글리프는 여러 코드 포인트 / 룬으로 만들 수 있습니다. reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks를 참조하십시오. 코드 포인트를 반전하면 결합 마크가 다른 기본 코드 포인트에 첨부됩니다.
고인돌

14

이것은 두 가지를 고려하여 유니 코드 문자열에서 작동합니다.

  • 범위 는 유니 코드 문자를 열거하여 문자열에서 작동합니다.
  • string은 각 요소가 유니 코드 문자 인 int 슬라이스로 구성 될 수 있습니다.

그래서 여기에 간다 :

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)-1for를 할당 한 다음 한 줄로 접습니다 for _, c:=range s { o[i--]=c; }. Man I HATE for without 괄호-이것이 허용 for(_, c:=range s) { o[i--]=c; }
Lawrence Dol

_의 기능을 설명해 주시겠습니까?
Lawrence Dol

6
@Software_Monkey : o [i--] = c는 Go에서 허용되지 않습니다. -및 ++는 표현식이 아니라 명령문입니다. _는 해당 변수를 무시 (무시)하는 것을 의미합니다.
Randy Sugianto 'Yuku'2009

1
이동으로 1.1 이상이 문자열에 오류를 반환합니다 ([] int)를 줄 경우 대신 [] 룬 유형은 O에 사용되는 모든 작품
Otuk

1
@yuku : 아직도의 실패 : = "레 미장센 \ u0301rables"
스테판 스타 이거

13

에서 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)
}

문자열 반전을위한 Go Playground

문자열 "bròwn"을 뒤집은 후 올바른 결과는 "nẁorb"가 아니라 "nwòrb"여야합니다.
문자 o 위의 무덤에 유의하십시오.


"as⃝df̅"와 역방향 결과 "f̅ds⃝a"와 같은 유니 코드 결합 문자를 보존
하려면 아래 나열된 다른 코드를 참조하십시오.

http://rosettacode.org/wiki/Reverse_a_string#Go


2
stackoverflow.com/a/10030772/3093387 과의 차이점을 설명해 주셔서 감사 합니다.이 두 솔루션은 "bròwn"과 같은 문자열을 처리하는 방식이 다른 것 같습니다.
josliber

핸들 문자를 결합하는 Rosettacode 솔루션 언급 주셔서 감사합니다
고인돌

11

나는 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 犬")))
}

1
return string (runes) 잘 작동합니다.

3
@Tommy : 아니요, return string(runes)모든 경우에 적용되는 것은 아닙니다.
peterSO

그 이유에 대해 좀 더 설명해 주시겠습니까? 내가 짧은 프로그램을 만들었는데 거기에서 작동하지만, 당신이 말하는 케이스가 거기에서 발생하지 않을 수 있습니까? play.golang.org/p/yk1sAwFjol

1
@Tommy : 귀하의 짧은 프로그램은 프린터 나 터미널로 보낼 때 NUL 문자가 NOP임을 보여줍니다. ASCII가 아닌 UTF-8 인코딩 문자열에 대해 Reverse2 함수가 실패합니다. 유효한 테스트입니다 그래서 나는 당신의 쇼트 프로그램을 수정했습니다 play.golang.org/p/Ic5G5QEO93
peterSO을

문자 결합을 제대로 처리하지 못하는 잘못된 "솔루션"이 하나 더 있습니다.
고인돌

9

여기에 너무 많은 답변이 있습니다. 그들 중 일부는 명확한 중복입니다. 그러나 왼쪽 에서조차 최상의 솔루션을 선택하기가 어렵습니다.

그래서 나는 답변을 살펴보고 유니 코드에서 작동하지 않는 것을 버리고 중복을 제거했습니다. 가장 빠른 것을 찾기 위해 생존자를 벤치마킹했습니다. 따라서 다음은 어트 리뷰 션을 사용한 결과 입니다 (내가 놓친 답변을 발견했지만 추가 할 가치가있는 경우 벤치 마크를 자유롭게 수정하십시오).

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=.


이러한 "솔루션"중 어느 것도 마크 결합을 올바르게 처리하지 않습니다 .
고인돌

6

ReverseUTF8 인코딩과 결합 된 문자를 존중 하는 다음 함수를 작성했습니다 .

// 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")
}

3

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 );
}

+1. 작동합니다. 그러나 나는 그러한 간단한 작업을 위해 분할과 결합이 필요하다는 것이 (현재로서는) 다소 이상하다고 말해야합니다.
Stephan202

@martin : 편집에 대해 죄송합니다. 실수로 귀하의 질문에 업데이트 된 답변을 붙여 넣었습니다 ... 매우 부끄럽습니다 .
Stephan202

@Stephan-문제 없습니다. strings package Bytes 함수를 기반으로 대체 솔루션을 추가했습니다.
martin clayton

@Nosradena : 같은 분 안에 롤백했습니다 (마틴이 내가 방금 작성한 것과 똑같은 텍스트로 답변을 업데이트 한 것을보고 놀랐습니다 ... 그리고 나에게 밝혔습니다.)
Stephan202

@martin : 질문하면 두 번째 버전이 더 좋아 보입니다. :)
Stephan202

3
//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 배 빠릅니다.


1
이 질문이 가장 정확한 답변 임에도 불구하고 왜 찬성표가 없는지 궁금합니다
Nilesh

3

다음은 상당히 다릅니다. 다른 답변에는 나열되지 않은 더 기능적인 접근 방식을 말합니다.

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}

나는 그것이 가장 빠른 해결책이 아니라고 확신하지만 ret, 각 지연 함수에 의해 추가 처리를 위해 반환 변수 가 어떻게 닫혀 있는지 보여줍니다 .
Vladimir Bauer

느리고 문자 결합을 제대로 처리하지 못합니다.
고인돌

1
얼마나 빠른지 모르겠지만 아름답습니다.
donatJ

이 성능은 Go 1.14에서 개선 될 수 있습니다. 적어도 릴리스 노트 는 지연 오버 헤드가 없다고 주장합니다.
Vladimir Bauer

2

이것은 가장 빠른 구현입니다

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)
    }
}

가장 빠른 구현이라고 주장하기 전에 솔루션을 벤치마킹 했습니까?
Denys Séguret 2014 년

네, 그렇기 때문에 BenchmarkReverse 코드가 있습니다 :). 그러나 나는 더 이상 결과가 없습니다.
rmuller 2014 년

빠른 솔루션이지만 문자 결합을 제대로 처리하지 못하기 때문에 여전히 잘못되었습니다.
고인돌

@dolmen이 이것이 문자 결합을 처리하지 않는다고 말했듯이 사실입니까? 여기에 해결책이 있습니까?
geraldss

2

이 코드는 문자 결합 시퀀스를 그대로 유지하며 잘못된 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참조하세요 .


문자열 값에 그런 "잘못된 UTF-8 입력"이 존재하지 않는다 : 변환 할 때 []byte까지 string이동 유효한 코드 포인트로 "잘못된 UTF-8 입력을"대체합니다 \uFFFD.
dolmen

위의 의견을 이해할 수 없습니다. 유효하지 않은 UTF-8이 포함 된 문자열이 표시 될 때이 코드의 동작이 잘못되었다는 말입니까?
rog

아니요 string. Go에 잘못된 UTF-8이 존재하지 않는다는 뜻입니다. 그러나 []byte.
고인돌

Go 문자열은 [] 바이트만큼의 유효하지 않은 utf-8을 포함 할 수 있습니다. 예 : play.golang.org/p/PG0I4FJfEN
rog

2

자소 클러스터를 처리해야하는 경우 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
}

나는 당신에게 1'000 개의 찬성표를주고 싶습니다. 이 페이지의 다른 모든 구현은 STRING을 잘못 반전합니다 (STRING은 문자 시퀀스가 ​​아님).
Stefan Steiger

이것은 작동하지 않습니다. 문자열을 두 번 뒤집 으면 원래 문자열을 얻지 못합니다. 이 예에서 사용 된 선행 조합 분음 기호 (\ u0308)는 반전 될 때 이중 움라우트 'a'를 만드는 선행 문자와 결합됩니다. 경우 str출력 인용은 최고의 견적을 수정합니다!
Joshua Kolden

2

기존 구현을 가져올 수도 있습니다.

import "4d63.com/strrev"

그때:

strrev.Reverse("abåd") // returns "dåba"

또는 유니 코드 조합 문자를 포함하는 문자열을 반전하려면 :

strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"

이러한 구현은 유니 코드 멀티 바이트의 올바른 순서 지정 및 반전시 문자 결합을 지원합니다.

참고 : 많은 프로그래밍 언어에서 내장 된 문자열 역방향 함수는 결합을 유지하지 않으며 결합 문자를 식별하는 데 훨씬 더 많은 실행 시간이 필요합니다.


1

확실히 가장 메모리 효율적인 솔루션은 아니지만 "간단한"UTF-8 안전 솔루션의 경우 다음은 작업을 완료하고 룬을 깨뜨리지 않습니다.

제 생각에는 페이지에서 가장 읽기 쉽고 이해하기 쉽습니다.

func reverseStr(str string) (out string) {
    for _, s := range str {
        out = string(s) + out
    }

    return
}

1

다음 두 가지 방법 은 문자 결합을 보존 하는 가장 빠른 솔루션 보다 더 빠르게 실행 되지만 벤치 마크 설정에서 뭔가 빠졌다는 의미는 아닙니다.

//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

벤치 마크에서 누락 된 부분은 다음과 같습니다. 결합 문자를 보존하지 않기 때문에 솔루션이 더 빠릅니다. 그것들을 비교하는 것은 불공평합니다.
dolmen

1

참고 : 이 답변은 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());
}

왜 모든 후행 세미콜론을 추가합니까?
Morteza R

@ olivier-mason Go 코드를 공유 할 때 gofmt에 대해 배울 때입니다.
고인돌

1
그 대답은 8 년 전의 것입니다.
Oliver Mason

@OliverMason 불완전한 솔루션을 수정 (또는 삭제)하기에 너무 늦지 않았습니다.
고인돌

0

유니 코드에서 작동하는 버전입니다. 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);
}

0

룬은 유형이므로 사용하십시오. 또한 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))
}

해당 질문이 게시 될 때 세미콜론을 사용했습니다.
OneOfOne 2014-12-02

문자 결합을 제대로 처리하지 못하는 잘못된 "솔루션"이 하나 더 있습니다.
고인돌


0

간단한 문자열의 경우 다음과 같은 구성을 사용할 수 있습니다.

func Reverse(str string) string {
    if str != "" {
        return Reverse(str[1:]) + str[:1]
    }
    return ""   
}

-1

또 다른 해결책은 다음과 같습니다.

func ReverseStr(s string) string {
    chars := []rune(s)
    rev := make([]rune, 0, len(chars))
    for i := len(chars) - 1; i >= 0; i-- {
        rev = append(rev, chars[i])
    }
    return string(rev)
}

그러나 위의 yazu의 솔루션은 []rune슬라이스를 제자리에서 뒤집기 때문에 더 우아 합니다.


-1

또 다른 솔루션 (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)
}

-1
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

입력이 NFC에있는 경우 작동합니다. 그러나 여기에있는 대부분의 다른 잘못된 솔루션과 마찬가지로 문자 결합에서는 작동하지 않습니다.
dolmen

-1
    func reverseString(someString string) string {
        runeString := []rune(someString)
        var reverseString string
        for i := len(runeString)-1; i >= 0; i -- {
            reverseString += string(runeString[i])
        }
        return reverseString
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.