हम गो में एक साधारण स्ट्रिंग को कैसे उल्टा कर सकते हैं?
हम गो में एक साधारण स्ट्रिंग को कैसे उल्टा कर सकते हैं?
जवाबों:
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)
}
रॉल कॉक्स, गोलंग-नट्स मेलिंग सूची पर , सुझाव देते हैं
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)
?
यह काम करता है, सभी कार्यों के बारे में mucking के बिना:
func Reverse(s string) (result string) {
for _,v := range s {
result = string(v) + result
}
return
}
यह 2 बातों पर विचार करके यूनिकोड स्ट्रिंग्स पर काम करता है:
तो यहाँ यह जाता है:
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 _, c:=range s { o[i--]=c; }
। मैन आई हेट फॉर द फॉर बिना कोष्ठक - क्या इसकी अनुमति है: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)
}
एक स्ट्रिंग रिवर्स करने के लिए खेल का मैदान जाओ
स्ट्रिंग "ब्रोवन" को उलटने के बाद, सही परिणाम "nwbrb" होना चाहिए, न कि "noror"।
पत्र ओ के ऊपर कब्र पर ध्यान दें।
यूनिकोड संयोजन जैसे कि "as Undf with" को उल्टे परिणाम "f̅dsica" के साथ संरक्षित
करने के लिए , कृपया नीचे सूचीबद्ध एक और कोड देखें:
मैंने इस सवाल पर गौर किया जब साइमन ने अपना समाधान पोस्ट किया , जो कि तार अपरिवर्तनीय हैं, बहुत अक्षम है। अन्य प्रस्तावित समाधान भी त्रुटिपूर्ण हैं; वे काम नहीं करते हैं या वे अक्षम हैं।
यहां एक कुशल समाधान है जो काम करता है, सिवाय इसके जब स्ट्रिंग वैध यूटीएफ -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
स्ट्रिंग्स का उपयोग करना। स्टड कॉन्टेनेशन का उपयोग करने की तुलना में ब्रैस्ट 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
अस्तित्व में नहीं है। लेकिन यह एक में मौजूद हो सकता है []byte
।
यदि आपको अंगूर के गुच्छों को संभालने की आवश्यकता है, तो यूनिकोड या रेगेक्स मॉड्यूल का उपयोग करें।
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"
ये कार्यान्वयन यूनिकोड मल्टीबाइट के सही क्रम का समर्थन करता है और उलट होने पर वर्णों का संयोजन करता है।
नोट: कई प्रोग्रामिंग भाषाओं में अंतर्निहित स्ट्रिंग रिवर्स फ़ंक्शन संयोजन को संरक्षित नहीं करते हैं, और संयोजन पात्रों की पहचान करने के लिए काफी अधिक निष्पादन समय की आवश्यकता होती है।
यह निश्चय ही सबसे अधिक स्मृति कुशल समाधान नहीं है, लेकिन "सरल" UTF-8 सुरक्षित समाधान के लिए निम्न कार्य किया जाएगा और रनों को नहीं तोड़ा जाएगा।
यह मेरी राय में पृष्ठ पर सबसे अधिक पठनीय और समझने योग्य है।
func reverseStr(str string) (out string) {
for _, s := range str {
out = string(s) + out
}
return
}
वर्णों के संयोजन को बनाए रखने वाले सबसे तेज़ समाधान की तुलना में निम्नलिखित दो विधियाँ तेज़ी से चलती हैं , हालांकि यह कहना नहीं है कि मुझे अपने बेंचमार्क सेटअप में कुछ याद आ रहा है।
//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 से है, इसलिए अब तक बेहतर समाधान हैं।
थोड़ा सा 'गोल चक्कर' दिखता है, और शायद बहुत कुशल नहीं है, लेकिन यह बताता है कि स्ट्रिंग्स से पढ़ने के लिए रीडर इंटरफ़ेस का उपयोग कैसे किया जा सकता है। जब utf8 तार के साथ काम कर रहे हो तो IntVector भी बफ़र के रूप में बहुत उपयुक्त लगते हैं।
'आकार ’वाले हिस्से को छोड़ते समय यह और भी छोटा होगा, और सम्मिलित रूप से वेक्टर में सम्मिलन होगा, लेकिन मुझे लगता है कि यह कम कुशल होगा, क्योंकि पूरे वेक्टर को फिर एक बार नया रन जोड़ने पर एक बार वापस धकेलने की आवश्यकता होती है। ।
यह समाधान निश्चित रूप से 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.une फ़ंक्शन पर बनाया गया है:
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);
}
रूण एक प्रकार है, इसलिए इसका उपयोग करें। इसके अलावा, गो अर्धविराम का उपयोग नहीं करता है।
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 ""
}
यहाँ अभी तक एक और समाधान है:
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)
}
हालाँकि, ऊपर यजु का समाधान अधिक सुरुचिपूर्ण है क्योंकि वह []rune
जगह में स्लाइस को उलट देता है।
अभी तक एक और समाधान (टीएम):
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+´
इसके बजाय देनाá
। मुझे आश्चर्य है कि इसे सामान्य करने के बिना, इसे कैसे ध्यान में रखा जा सकता है।