एक स्ट्रिंग को रिवर्स करने का सबसे अच्छा तरीका


440

मुझे सिर्फ C # 2.0 में एक स्ट्रिंग रिवर्स फ़ंक्शन लिखना है (यानी LINQ उपलब्ध नहीं है) और इसके साथ आया:

public string Reverse(string text)
{
    char[] cArray = text.ToCharArray();
    string reverse = String.Empty;
    for (int i = cArray.Length - 1; i > -1; i--)
    {
        reverse += cArray[i];
    }
    return reverse;
}

व्यक्तिगत रूप से मैं समारोह के बारे में पागल नहीं हूं और आश्वस्त हूं कि ऐसा करने का एक बेहतर तरीका है। है?


51
यदि आप उचित अंतरराष्ट्रीय समर्थन चाहते हैं तो हैरानी की बात है। उदाहरण: क्रोएशियाई / सर्बियाई में दो-वर्ण अक्षर lj, nj आदि हैं। "लजुड़ी" का उचित उल्टा "इडुलज" है, न कि "इडूजल"। मुझे यकीन है कि आप भी बदतर प्रदर्शन किया था जब यह अरबी के लिए आता हूँ, थाई आदि
dbkk

मुझे आश्चर्य है कि अगर यह एक अस्थायी सरणी को शुरू करने और उस में परिणाम संग्रहीत करने के बजाय एक स्ट्रिंग को समतल करने के लिए धीमा है, और फिर अंत में इसे एक स्ट्रिंग में परिवर्तित कर रहा है?
मफिन मैन


5
इस प्रश्न को "सर्वश्रेष्ठ" द्वारा परिभाषित करने से बेहतर किया जा सकता है। सबसे तेजी से? सबसे पठनीय? विभिन्न किनारे के मामलों में सबसे विश्वसनीय (अशक्त जांच, कई भाषाओं, आदि)? C # और .NET के संस्करणों में सबसे अधिक रखरखाव योग्य है?
hypehuman

जवाबों:


608
public static string Reverse( string s )
{
    char[] charArray = s.ToCharArray();
    Array.Reverse( charArray );
    return new string( charArray );
}

16
sambo99: इसमें यूनिकोड का उल्लेख करने की आवश्यकता नहीं है: C # में चार्ट यूनिकोड वर्ण हैं, बाइट्स नहीं। Xor तेज हो सकता है, लेकिन इसके अलावा कम पठनीय होने के अलावा, यह भी हो सकता है कि Array.Reverse () आंतरिक रूप से उपयोग करता है।
निक जॉनसन

27
@ अर्चना: दरअसल, C # में वर्ण UTF-16 कोड इकाइयाँ हैं; यह उनमें से दो को एक पूरक चरित्र का प्रतिनिधित्व करने के लिए लेता है। Jaggersoft.com/csharp_standard/9.4.1.htm देखें ।
ब्रैडली ग्रिंगर

4
हाँ sambo99 मुझे लगता है कि आप सही हैं, लेकिन यह UTF-32 का उपयोग करने के लिए एक बहुत ही दुर्लभ मामला है। और XOR मूल्यों की एक बहुत छोटी श्रृंखला के लिए केवल तेजी से है, सही उत्तर मैं अलग-अलग लंबाई के लिए अलग-अलग तरीकों को लागू करने के लिए होगा जो मुझे लगता है। लेकिन यह स्पष्ट और संक्षिप्त है जो मेरी राय में एक लाभ है।
15

21
यूनिकोड नियंत्रण वर्ण इस विधि को गैर लैटिन वर्ण सेटों के लिए बेकार बनाता है। जॉन कठपुतली स्पष्टीकरण देखें, एक जुर्राब कठपुतली का उपयोग करके: codeblog.jonskeet.uk/2009/11/02/… (1/4 जिस तरह से नीचे), या वीडियो: vimeo.com/7516539
Callum रोजर्स

20
आशा है कि आप किसी भी सरोगेट या संयोजन पात्रों का सामना नहीं करेंगे।
dalle

183

यहां एक समाधान जो स्ट्रिंग "Les Mise\u0301rables"को ठीक से उलट देता है "selbare\u0301siM seL"। इसे वैसे ही प्रस्तुत करना चाहिए selbarésiM seL, न कि selbaŕesiM seL(उच्चारण की स्थिति पर ध्यान दें), जैसा कि कोड इकाइयों ( Array.Reverse, आदि) या यहां तक ​​कि कोड पॉइंट (सरोगेट जोड़े के लिए विशेष देखभाल के साथ उलट) के आधार पर अधिकांश कार्यान्वयन का परिणाम होगा ।

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

public static class Test
{
    private static IEnumerable<string> GraphemeClusters(this string s) {
        var enumerator = StringInfo.GetTextElementEnumerator(s);
        while(enumerator.MoveNext()) {
            yield return (string)enumerator.Current;
        }
    }
    private static string ReverseGraphemeClusters(this string s) {
        return string.Join("", s.GraphemeClusters().Reverse().ToArray());
    }

    public static void Main()
    {
        var s = "Les Mise\u0301rables";
        var r = s.ReverseGraphemeClusters();
        Console.WriteLine(r);
    }
}

(और यहां लाइव चल रहा उदाहरण: https://ideone.com/DqAeMJ )

यह केवल grapheme क्लस्टर पुनरावृत्ति के लिए .NET एपीआई का उपयोग करता है , जो कि पहले से ही है, लेकिन देखने से थोड़ा "छिपा हुआ" है, ऐसा लगता है।


10
+1 बहुत कम सही उत्तरों में से एक , और किसी भी अन्य की तुलना में बहुत अधिक सुरुचिपूर्ण और भविष्य का प्रमाण, IMO
sehe

यह कुछ स्थानीय निर्भर सामान के लिए विफल रहता है, हालांकि।
आर। मार्टिनो फर्नांडिस

7
यह हास्यास्पद है कि कैसे अन्य उत्तरदाताओं में से अधिकांश एमएस को दाढ़ी बनाने की कोशिश कर रहे हैं जो अन्यथा गलत दृष्टिकोण हैं। कैसे प्रतिनिधि
जी। स्टोयनेव

2
यह वास्तव में StringInfo (s) को त्वरित करने के लिए काफी तेज है, फिर सबस्ट्रिंगबायटेक्स्टाइल (x, 1) के माध्यम से पुनरावृति करें और एक स्ट्रिंग के साथ एक नया स्ट्रिंग बनाएं।

2
यह थोड़ा अजीब है कि आपने जॉन स्कीट के उदाहरण का उपयोग किया है जो उन्होंने सालों पहले दिए गए codeblog.jonskeet.uk/2009/11/02// लेस मिसरेबल्स (हालांकि जॉन ने एक समाधान का उल्लेख नहीं किया है, उन्होंने सिर्फ मुद्दों को सूचीबद्ध किया है)। अच्छा है कि आप एक समाधान के साथ आए। शायद जॉन स्कीट ने एक टाइम मशीन का आविष्कार किया, 2009 तक वापस चला गया और समस्या का उदाहरण पोस्ट किया जो आपने अपने समाधान में उपयोग किया था।
बारलोप

126

यह आश्चर्यजनक रूप से मुश्किल सवाल है।

मैं ज्यादातर मामलों के लिए Array.Reverse का उपयोग करने की सलाह दूंगा क्योंकि यह देशी रूप से कोडित है और इसे बनाए रखना और समझना बहुत सरल है।

ऐसा लगता है कि मैंने जिन सभी मामलों का परीक्षण किया, उनमें स्ट्रिंगबर्ल को बेहतर बनाना था।

public string Reverse(string text)
{
   if (text == null) return null;

   // this was posted by petebob as well 
   char[] array = text.ToCharArray();
   Array.Reverse(array);
   return new String(array);
}

एक दूसरा दृष्टिकोण है जो कुछ स्ट्रिंग लंबाई के लिए तेज हो सकता है जो Xor का उपयोग करता है

    public static string ReverseXor(string s)
    {
        if (s == null) return null;
        char[] charArray = s.ToCharArray();
        int len = s.Length - 1;

        for (int i = 0; i < len; i++, len--)
        {
            charArray[i] ^= charArray[len];
            charArray[len] ^= charArray[i];
            charArray[i] ^= charArray[len];
        }

        return new string(charArray);
    }

नोट यदि आप पूर्ण यूनिकोड UTF16 चार्ट का समर्थन करना चाहते हैं तो इसे पढ़ें । और इसके बजाय वहाँ कार्यान्वयन का उपयोग करें। यह उपरोक्त एल्गोरिदम में से एक का उपयोग करके और तार के उलट होने के बाद इसे साफ करने के लिए स्ट्रिंग के माध्यम से आगे अनुकूलित किया जा सकता है।

यहाँ StringBuilder, Array.Reverse और Xor पद्धति के बीच एक प्रदर्शन तुलना है।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication4
{
    class Program
    {
        delegate string StringDelegate(string s);

        static void Benchmark(string description, StringDelegate d, int times, string text)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int j = 0; j < times; j++)
            {
                d(text);
            }
            sw.Stop();
            Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times);
        }

        public static string ReverseXor(string s)
        {
            char[] charArray = s.ToCharArray();
            int len = s.Length - 1;

            for (int i = 0; i < len; i++, len--)
            {
                charArray[i] ^= charArray[len];
                charArray[len] ^= charArray[i];
                charArray[i] ^= charArray[len];
            }

            return new string(charArray);
        }

        public static string ReverseSB(string text)
        {
            StringBuilder builder = new StringBuilder(text.Length);
            for (int i = text.Length - 1; i >= 0; i--)
            {
                builder.Append(text[i]);
            }
            return builder.ToString();
        }

        public static string ReverseArray(string text)
        {
            char[] array = text.ToCharArray();
            Array.Reverse(array);
            return (new string(array));
        }

        public static string StringOfLength(int length)
        {
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
            }
            return sb.ToString();
        }

        static void Main(string[] args)
        {

            int[] lengths = new int[] {1,10,15,25,50,75,100,1000,100000};

            foreach (int l in lengths)
            {
                int iterations = 10000;
                string text = StringOfLength(l);
                Benchmark(String.Format("String Builder (Length: {0})", l), ReverseSB, iterations, text);
                Benchmark(String.Format("Array.Reverse (Length: {0})", l), ReverseArray, iterations, text);
                Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text);

                Console.WriteLine();    
            }

            Console.Read();
        }
    }
}

यहाँ परिणाम हैं:

26251 Ticks String Builder (Length: 1) : called 10000 times.
33373 Ticks Array.Reverse (Length: 1) : called 10000 times.
20162 Ticks Xor (Length: 1) : called 10000 times.

51321 Ticks String Builder (Length: 10) : called 10000 times.
37105 Ticks Array.Reverse (Length: 10) : called 10000 times.
23974 Ticks Xor (Length: 10) : called 10000 times.

66570 Ticks String Builder (Length: 15) : called 10000 times.
26027 Ticks Array.Reverse (Length: 15) : called 10000 times.
24017 Ticks Xor (Length: 15) : called 10000 times.

101609 Ticks String Builder (Length: 25) : called 10000 times.
28472 Ticks Array.Reverse (Length: 25) : called 10000 times.
35355 Ticks Xor (Length: 25) : called 10000 times.

161601 Ticks String Builder (Length: 50) : called 10000 times.
35839 Ticks Array.Reverse (Length: 50) : called 10000 times.
51185 Ticks Xor (Length: 50) : called 10000 times.

230898 Ticks String Builder (Length: 75) : called 10000 times.
40628 Ticks Array.Reverse (Length: 75) : called 10000 times.
78906 Ticks Xor (Length: 75) : called 10000 times.

312017 Ticks String Builder (Length: 100) : called 10000 times.
52225 Ticks Array.Reverse (Length: 100) : called 10000 times.
110195 Ticks Xor (Length: 100) : called 10000 times.

2970691 Ticks String Builder (Length: 1000) : called 10000 times.
292094 Ticks Array.Reverse (Length: 1000) : called 10000 times.
846585 Ticks Xor (Length: 1000) : called 10000 times.

305564115 Ticks String Builder (Length: 100000) : called 10000 times.
74884495 Ticks Array.Reverse (Length: 100000) : called 10000 times.
125409674 Ticks Xor (Length: 100000) : called 10000 times.

ऐसा लगता है कि शॉर्ट स्ट्रिंग्स के लिए Xor तेज हो सकता है।


2
यह एक स्ट्रिंग वापस नहीं करता है - आपको इसे "नई स्ट्रिंग (...)" पर कॉल करने की आवश्यकता है
ग्रेग बीच

BTW .. मैं सिर्फ Array.Reverse के कार्यान्वयन पर एक नज़र था, और इसके भोलेपन के लिए किया ... यह StringBuilder विकल्प की तुलना में बहुत तेज होना चाहिए।
सैम केसर

तुम कितने अच्छे हो, ग्रेग, सैम्बो को रोकने के लिए उसे वोट देने के बजाय एक बेहतर समाधान पर पहुंचे।
डीओके

@ dok1 - इसका जिक्र न करें :) @ sambo99 - अब मैं एक साज़िश कर रहा हूँ, कल एक कोड प्रोफाइलर को कोड़ा मारना होगा और एक नज़र रखना होगा!
ग्रेग बीच

9
ये विधियाँ आधार बहुभाषी विमान के बाहर वाले वर्णों को संभालती नहीं हैं, अर्थात, यूनिकोड वर्ण> = U + 10000 जिन्हें दो C # वर्णों के साथ दर्शाया गया है। मैंने एक उत्तर पोस्ट किया है जो ऐसे तार को सही ढंग से संभालता है।
ब्रैडली ग्रिंजर

52

यदि आप एक लाइनर का अनुसरण करने की तुलना में LINQ (.NET फ्रेमवर्क 3.5+) का उपयोग कर सकते हैं, तो आपको शॉर्ट कोड मिलेगा। using System.Linq;करने के लिए उपयोग करने के लिए जोड़ने के लिए मत भूलना Enumerable.Reverse:

public string ReverseString(string srtVarable)
{
    return new string(srtVarable.Reverse().ToArray());
}

टिप्पणियाँ:

  • सबसे तेज़ संस्करण नहीं - मार्टिन निडरेल के अनुसार यहां सबसे तेज विकल्प से 5.7 गुना धीमा।
  • इस कोड के रूप में कई अन्य विकल्प पूरी तरह से बहु-चरित्र संयोजनों की अनदेखी करते हैं, इसलिए होमवर्क असाइनमेंट और स्ट्रिंग्स के उपयोग को सीमित करें जिसमें ऐसे वर्ण शामिल नहीं हैं। कार्यान्वयन के लिए इस सवाल का एक और जवाब देखें जो इस तरह के संयोजनों को सही ढंग से संभालता है।

यह सबसे अपग्रेड किए गए संस्करण की तुलना में लगभग 5.7 गुना धीमा है, इसलिए मैं इसका उपयोग करने की सलाह नहीं दूंगा!
मार्टिन निडरेल

2
सबसे तेज समाधान नहीं है, लेकिन एक-लाइनर के रूप में उपयोगी है।
एड्रिंपम्प

49

यदि स्ट्रिंग में यूनिकोड डेटा (सख्ती से बोलना, गैर-बीएमपी वर्ण) शामिल हैं, तो पोस्ट की गई अन्य विधियां इसे भ्रष्ट कर देंगी, क्योंकि आप स्ट्रिंग को उलटते समय उच्च और निम्न सरोगेट कोड इकाइयों के आदेश को स्वैप नहीं कर सकते हैं। (इसके बारे में अधिक जानकारी मेरे ब्लॉग पर मिल सकती है ।)

निम्न कोड नमूना एक स्ट्रिंग को सही ढंग से उलट देगा जिसमें गैर-बीएमपी वर्ण होते हैं, उदाहरण के लिए, "\ U00010380 \ U00010381" (Ugaritic Letter Alpa, Ugaritic Letter Beta)।

public static string Reverse(this string input)
{
    if (input == null)
        throw new ArgumentNullException("input");

    // allocate a buffer to hold the output
    char[] output = new char[input.Length];
    for (int outputIndex = 0, inputIndex = input.Length - 1; outputIndex < input.Length; outputIndex++, inputIndex--)
    {
        // check for surrogate pair
        if (input[inputIndex] >= 0xDC00 && input[inputIndex] <= 0xDFFF &&
            inputIndex > 0 && input[inputIndex - 1] >= 0xD800 && input[inputIndex - 1] <= 0xDBFF)
        {
            // preserve the order of the surrogate pair code units
            output[outputIndex + 1] = input[inputIndex];
            output[outputIndex] = input[inputIndex - 1];
            outputIndex++;
            inputIndex--;
        }
        else
        {
            output[outputIndex] = input[inputIndex];
        }
    }

    return new string(output);
}

29
दरअसल, C # में चार्ट 16-बिट UTF-16 कोड इकाइयाँ हैं; एक पूरक चरित्र उनमें से दो का उपयोग कर एन्कोड किया गया है, इसलिए यह आवश्यक है,
ब्रैडली ग्रिंजर

14
ऐसा लगता है कि System.String वास्तव में यूनिकोड के पूरक वर्ण वाले स्ट्रिंग्स के लिए HereBeDragons गुण को उजागर करना चाहिए।
रॉबर्ट रॉसनी

4
@SebastianNegraszus: यह सही है: यह विधि स्ट्रिंग में कोडपाइंट्स को उलट देती है। पीछे ग्रफीम समूहों शायद और अधिक "उपयोगी" कुल मिलाकर (लेकिन क्या पहली जगह में एक मनमाना स्ट्रिंग पीछे के "उपयोग" है?) होगा, लेकिन आसान के साथ लागू करने के लिए नहीं है, बस में निर्मित .NET फ्रेमवर्क में तरीकों।
ब्रैडली ग्रिंगर

2
@ रीचर्ड: अंगूर के गुच्छों को तोड़ने के नियम केवल कोड बिंदुओं का पता लगाने की तुलना में थोड़ा अधिक जटिल हैं; अधिक जानकारी के लिए UAX # 29 में ग्रेपैम क्लस्टर सीमाओं पर प्रलेखन देखें।
ब्रैडली ग्रिंजर

1
बहुत अच्छी जानकारी! क्या किसी के पास Array.Reverse टेस्ट के लिए एक असफल परीक्षा है? और परीक्षण से मेरा मतलब है कि एक नमूना स्ट्रिंग एक पूरी इकाई परीक्षण नहीं है ... यह वास्तव में मुझे (और अन्य) इस मुद्दे के बारे में अलग-अलग व्यक्तियों को समझाने में मदद करेगा
आंद्रेई R 2nea

25

ठीक है, "अपने आप को दोहराएं नहीं" के हित में, मैं निम्नलिखित समाधान प्रदान करता हूं:

public string Reverse(string text)
{
   return Microsoft.VisualBasic.Strings.StrReverse(text);
}

मेरी समझ यह है कि यह कार्यान्वयन, VB.NET में डिफ़ॉल्ट रूप से उपलब्ध है, ठीक से यूनिकोड वर्णों को संभालता है।


11
यह केवल सरोगेट को ठीक से संभालता है। यह संयोजन चिह्नों को गड़बड़ करता है: ideone.com/yikdqX
आर। मार्टिनो फर्नांडीस

17

ग्रेग बीच ने एक unsafeविकल्प पोस्ट किया है जो वास्तव में जितना तेज़ हो जाता है (यह एक जगह में उलट है); लेकिन, जैसा कि उन्होंने अपने जवाब में संकेत दिया, यह पूरी तरह से विनाशकारी विचार है

उस ने कहा, मुझे आश्चर्य है कि इतनी आम सहमति है कि Array.Reverseसबसे तेज़ तरीका है। अभी भी एक unsafeदृष्टिकोण है जो एक स्ट्रिंग की उलटी प्रतिलिपि लौटाता है (कोई इन-प्लेस रिवर्सल शेंनिगन्स) छोटे तारों के लिए विधि की तुलना में काफी तेज हैArray.Reverse :

public static unsafe string Reverse(string text)
{
    int len = text.Length;

    // Why allocate a char[] array on the heap when you won't use it
    // outside of this method? Use the stack.
    char* reversed = stackalloc char[len];

    // Avoid bounds-checking performance penalties.
    fixed (char* str = text)
    {
        int i = 0;
        int j = i + len - 1;
        while (i < len)
        {
            reversed[i++] = str[j--];
        }
    }

    // Need to use this overload for the System.String constructor
    // as providing just the char* pointer could result in garbage
    // at the end of the string (no guarantee of null terminator).
    return new string(reversed, 0, len);
}

यहाँ कुछ बेंचमार्क परिणाम दिए गए हैं

आप देख सकते हैं कि प्रदर्शन लाभ सिकुड़ जाता है और फिर Array.Reverseविधि के खिलाफ गायब हो जाता है क्योंकि तार बड़े हो जाते हैं। छोटे से मध्यम आकार के तारों के लिए, हालांकि, इस पद्धति को हरा पाना कठिन है।


2
StackOverflow बड़े स्ट्रिंग्स पर।
रज़ मेग्रेलिडेज़

@rezomegreldize: हां, यह होगा;)
दान ताओ

15

आसान और अच्छा उत्तर एक्सटेंशन विधि का उपयोग कर रहा है:

static class ExtentionMethodCollection
{
    public static string Inverse(this string @base)
    {
        return new string(@base.Reverse().ToArray());
    }
}

और यहाँ उत्पादन है:

string Answer = "12345".Inverse(); // = "54321"

Reverse()और ToArray()आपके कोड नमूने में गलत क्रम में हैं।
क्रिस वॉल्श

@ किस उद्देश्य से सेवा करता है?
user5389726598465

2
: @ user5389726598465 यह लिंक देखें docs.microsoft.com/en-us/dotnet/csharp/language-reference/... क्योंकि 'आधार' सी # में एक कीवर्ड है, यह एक के रूप में यह व्याख्या करने के लिए सी # संकलक के लिए @ साथ उपसर्ग होना चाहिए, पहचानकर्ता।
डायंड्रिलिया

14

यदि आप वास्तव में खतरनाक खेल खेलना चाहते हैं, तो यह अब तक का सबसे तेज तरीका है (लगभग चार गुना तेजी से Array.Reverse विधि की )। यह पॉइंटर्स का उपयोग करके इन-प्लेस रिवर्स है।

ध्यान दें कि मैं वास्तव में किसी भी उपयोग के लिए यह अनुशंसा नहीं करता हूं, कभी भी ( कुछ कारणों के लिए यहां एक नज़र डालें कि आपको इस पद्धति का उपयोग क्यों नहीं करना चाहिए ), लेकिन यह देखना दिलचस्प है कि यह किया जा सकता है, और यह तार वास्तव में अपरिवर्तनीय नहीं हैं एक बार जब आप असुरक्षित कोड चालू करते हैं।

public static unsafe string Reverse(string text)
{
    if (string.IsNullOrEmpty(text))
    {
        return text;
    }

    fixed (char* pText = text)
    {
        char* pStart = pText;
        char* pEnd = pText + text.Length - 1;
        for (int i = text.Length / 2; i >= 0; i--)
        {
            char temp = *pStart;
            *pStart++ = *pEnd;
            *pEnd-- = temp;
        }

        return text;
    }
}

मुझे पूरा यकीन है कि यह utf16 स्ट्रिंग्स के लिए गलत परिणाम लौटाएगा, यह वास्तव में परेशानी पूछ रहा है :)
सैम केसर

हाय आप इस पोस्ट को इस stackoverflow.com/questions/229346/… पर लिंक करें , जैसा कि मैंने पहले कहा था कि यह वास्तव में परेशानी पूछ रहा है ...
सैम सैफ्रन

यह पूरी तरह से बुराई और बीमार-सलाह हो सकती है (जैसा कि आप खुद मानते हैं), लेकिन unsafeकोड का उपयोग करके स्ट्रिंग को उलटने के लिए अभी भी एक उच्च-प्रदर्शन तरीका है जो बुराई नहीं है और अभी भीArray.Reverse कई मामलों में धड़कता है। मेरे जवाब पर एक नजर।
दान ताओ

13

यहाँ विकिपीडिया प्रविष्टि पर एक नज़र डालें । वे String.Reverse एक्सटेंशन पद्धति को लागू करते हैं। यह आपको इस तरह कोड लिखने की अनुमति देता है:

string s = "olleh";
s.Reverse();

वे ToCharArray / रिवर्स संयोजन का उपयोग करते हैं जो इस प्रश्न के अन्य उत्तर सुझाते हैं। स्रोत कोड इस तरह दिखता है:

public static string Reverse(this string input)
{
    char[] chars = input.ToCharArray();
    Array.Reverse(chars);
    return new String(chars);
}

यह अद्भुत है, सिवाय इसके कि विस्तार के तरीकों को c # 2.0 में पेश नहीं किया गया।
कोबी

11

सबसे पहले आपको कॉल करने की आवश्यकता नहीं है ToCharArrayक्योंकि एक स्ट्रिंग को पहले से ही एक चार सरणी के रूप में अनुक्रमित किया जा सकता है, इसलिए यह आपको आवंटन से बचाएगा।

अगला अनुकूलन StringBuilderअनावश्यक आवंटन को रोकने के लिए उपयोग करना है (जैसा कि तार अपरिवर्तनीय हैं, उन्हें बदलते हुए प्रत्येक बार स्ट्रिंग की एक प्रतिलिपि बनाता है)। इसे और अधिक अनुकूलित करने के लिए हमने इसकी लंबाई पूर्व निर्धारित की StringBuilderताकि इसके बफर का विस्तार करने की आवश्यकता न पड़े।

public string Reverse(string text)
{
    if (string.IsNullOrEmpty(text))
    {
        return text;
    }

    StringBuilder builder = new StringBuilder(text.Length);
    for (int i = text.Length - 1; i >= 0; i--)
    {
        builder.Append(text[i]);
    }

    return builder.ToString();
}

संपादित करें: प्रदर्शन डेटा

मैंने इस फ़ंक्शन और Array.Reverseनिम्न सरल प्रोग्राम का उपयोग करके फ़ंक्शन का परीक्षण किया , जहां Reverse1एक फ़ंक्शन है और Reverse2अन्य है:

static void Main(string[] args)
{
    var text = "abcdefghijklmnopqrstuvwxyz";

    // pre-jit
    text = Reverse1(text); 
    text = Reverse2(text);

    // test
    var timer1 = Stopwatch.StartNew();
    for (var i = 0; i < 10000000; i++)
    {
        text = Reverse1(text);
    }

    timer1.Stop();
    Console.WriteLine("First: {0}", timer1.ElapsedMilliseconds);

    var timer2 = Stopwatch.StartNew();
    for (var i = 0; i < 10000000; i++)
    {
        text = Reverse2(text);
    }

    timer2.Stop();
    Console.WriteLine("Second: {0}", timer2.ElapsedMilliseconds);

    Console.ReadLine();
}

यह पता चला है कि छोटे तारों के लिए Array.Reverseविधि ऊपर वाले की तुलना में लगभग दोगुनी है, और लंबे समय तक स्ट्रिंग के लिए अंतर और भी अधिक स्पष्ट है। तो यह देखते हुए कि Array.Reverseविधि सरल और तेज दोनों है, मैं आपको इसके बजाय इसका उपयोग करने की सलाह दूंगा। मैं यह दिखाने के लिए इसे यहाँ छोड़ता हूँ कि यह ऐसा नहीं है जो आपको करना चाहिए (मेरे आश्चर्य को बहुत कुछ!)


पाठ को संग्रहीत नहीं किया जाएगा। एक चर में थोड़ा और गति दें क्योंकि आप एक वस्तु के माध्यम से इसे संदर्भित कर रहे हैं?
डेविड रोबिन्स

10

Array.Reverse का उपयोग करके देखें


public string Reverse(string str)
{
    char[] array = str.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}

यह अविश्वसनीय रूप से तेज है।
माइकल Stum

क्यों गिरा वोट? यह बहस नहीं है, लेकिन मैं अपनी गलतियों से सीखूंगा।
माइक टू

कई अन्य चीजों के बीच संयोजन बिंदुओं को संभालने में विफल रहता है।
मूइंग डक

@MooDDuck - समझाने के लिए धन्यवाद, लेकिन मुझे नहीं पता कि आप कोड बिंदुओं से क्या मतलब है। इसके अलावा आप "कई अन्य चीजों" पर विस्तार से बता सकते हैं।
माइक टू

@MooDDuck मैंने कोड पॉइंट देखे। हाँ। तुम सही हो। यह कोड पॉइंट्स को हैंडल नहीं करता है। ऐसे सरल दिखने वाले प्रश्न के लिए सभी आवश्यकताओं को निर्धारित करना कठिन है। प्रतिक्रिया के लिए धन्यवाद
माइक टू

10
public static string Reverse(string input)
{
    return string.Concat(Enumerable.Reverse(input));
}

बेशक आप रिवर्स विधि के साथ स्ट्रिंग क्लास का विस्तार कर सकते हैं

public static class StringExtensions
{
    public static string Reverse(this string input)
    {
        return string.Concat(Enumerable.Reverse(input));
    }
}

Enumerable.Reverse(input)बराबर हैinput.Reverse()
fubo

8

"बेस्ट" कई चीजों पर निर्भर कर सकता है, लेकिन यहां कुछ और छोटे विकल्प दिए गए हैं जो तेजी से धीमी गति से दिए गए हैं:

string s = "z̽a̎l͘g̈o̓😀😆", pattern = @"(?s).(?<=(?:.(?=.*$(?<=((\P{M}\p{C}?\p{M}*)\1?))))*)";

string s1 = string.Concat(s.Reverse());                          // "☐😀☐̓ög͘l̎a̽z"  👎

string s2 = Microsoft.VisualBasic.Strings.StrReverse(s);         // "😆😀o̓g̈l͘a̎̽z"  👌

string s3 = string.Concat(StringInfo.ParseCombiningCharacters(s).Reverse()
    .Select(i => StringInfo.GetNextTextElement(s, i)));          // "😆😀o̓g̈l͘a̎z̽"  👍

string s4 = Regex.Replace(s, pattern, "$2").Remove(s.Length);    // "😆😀o̓g̈l͘a̎z̽"  👍

8

.NET Core 2.1 से शुरू करके स्ट्रिंग का उपयोग करके रिवर्स करने का एक नया तरीका है string.Create विधि ।

ध्यान दें कि यह समाधान यूनिकोड संयोजन वर्ण आदि को सही तरीके से नहीं संभालता है, क्योंकि "लेस मिसे \ u0301rables" को "selbarésiM seL" में बदल दिया जाएगा। अन्य उत्तर एक बेहतर समाधान के लिए।

public static string Reverse(string input)
{
    return string.Create<string>(input.Length, input, (chars, state) =>
    {
        state.AsSpan().CopyTo(chars);
        chars.Reverse();
    });
}

यह अनिवार्य रूप inputसे एक नए स्ट्रिंग के पात्रों को कॉपी करता है और नए स्ट्रिंग को इन-प्लेस में उलट देता है।

क्यों string.Createउपयोगी है?

जब हम मौजूदा सरणी से एक स्ट्रिंग बनाते हैं, तो एक नया आंतरिक सरणी आवंटित किया जाता है और मूल्यों की प्रतिलिपि बनाई जाती है। अन्यथा, इसके निर्माण (सुरक्षित वातावरण में) के बाद एक स्ट्रिंग को म्यूट करना संभव होगा। अर्थात्, निम्नलिखित स्निपेट में हमें 10 की लंबाई को दो बार आवंटित करना होगा, एक को बफर के रूप में और एक को स्ट्रिंग के आंतरिक सरणी के रूप में।

var chars = new char[10];
// set array values
var str = new string(chars);

string.Createअनिवार्य रूप से हमें स्ट्रिंग के निर्माण समय के दौरान आंतरिक सरणी में हेरफेर करने की अनुमति देता है। यह है, हमें अब बफर की आवश्यकता नहीं है और इसलिए उस एक चार सरणी को आवंटित करने से बच सकते हैं।

स्टीव गॉर्डन ने इसके बारे में अधिक विस्तार से यहां लिखा हैMSDN पर एक लेख भी है ।

कैसे करें इस्तेमाल string.Create?

public static string Create<TState>(int length, TState state, SpanAction<char, TState> action);

विधि तीन पैरामीटर लेता है:

  1. बनाने के लिए स्ट्रिंग की लंबाई,
  2. वह डेटा जिसे आप नए स्ट्रिंग को गतिशील रूप से बनाने के लिए उपयोग करना चाहते हैं,
  3. और एक प्रतिनिधि जो डेटा से अंतिम स्ट्रिंग बनाता है, जहां पहला पैरामीटर charनए स्ट्रिंग के आंतरिक सरणी को इंगित करता है और दूसरा वह डेटा (स्थिति) है जिसे आपने पास किया था string.Create

प्रतिनिधि के अंदर हम निर्दिष्ट कर सकते हैं कि डेटा से नया स्ट्रिंग कैसे बनाया जाता है। हमारे मामले में, हम Spanनए स्ट्रिंग द्वारा प्रयुक्त इनपुट स्ट्रिंग के अक्षरों को कॉपी करते हैं । फिर हम उल्टा करते हैं Spanऔर इसलिए पूरी स्ट्रिंग उलट जाती है।

मानक

स्वीकृत उत्तर के साथ एक स्ट्रिंग को उलटने के मेरे प्रस्तावित तरीके की तुलना करने के लिए, मैंने बेंचमार्कडॉटनेट का उपयोग करते हुए दो बेंचमार्क लिखे हैं।

public class StringExtensions
{
    public static string ReverseWithArray(string input)
    {
        var charArray = input.ToCharArray();
        Array.Reverse(charArray);
        return new string(charArray);
    }

    public static string ReverseWithStringCreate(string input)
    {
        return string.Create(input.Length, input, (chars, state) =>
        {
            state.AsSpan().CopyTo(chars);
            chars.Reverse();
        });
    }
}

[MemoryDiagnoser]
public class StringReverseBenchmarks
{
    private string input;

    [Params(10, 100, 1000)]
    public int InputLength { get; set; }


    [GlobalSetup]
    public void SetInput()
    {
        // Creates a random string of the given length
        this.input = RandomStringGenerator.GetString(InputLength);
    }

    [Benchmark(Baseline = true)]
    public string WithReverseArray() => StringExtensions.ReverseWithArray(input);

    [Benchmark]
    public string WithStringCreate() => StringExtensions.ReverseWithStringCreate(input);
}

यहाँ मेरी मशीन पर परिणाम हैं:

| Method           | InputLength |         Mean |      Error |    StdDev |  Gen 0 | Allocated |
| ---------------- | ----------- | -----------: | ---------: | --------: | -----: | --------: |
| WithReverseArray | 10          |    45.464 ns |  0.4836 ns | 0.4524 ns | 0.0610 |      96 B |
| WithStringCreate | 10          |    39.749 ns |  0.3206 ns | 0.2842 ns | 0.0305 |      48 B |
|                  |             |              |            |           |        |           |
| WithReverseArray | 100         |   175.162 ns |  2.8766 ns | 2.2458 ns | 0.2897 |     456 B |
| WithStringCreate | 100         |   125.284 ns |  2.4657 ns | 2.0590 ns | 0.1473 |     232 B |
|                  |             |              |            |           |        |           |
| WithReverseArray | 1000        | 1,523.544 ns |  9.8808 ns | 8.7591 ns | 2.5768 |    4056 B |
| WithStringCreate | 1000        | 1,078.957 ns | 10.2948 ns | 9.6298 ns | 1.2894 |    2032 B |

जैसा कि आप देख सकते हैं, ReverseWithStringCreateहम ReverseWithArrayविधि द्वारा उपयोग की जाने वाली स्मृति का केवल आधा हिस्सा आवंटित करते हैं ।



7

एक समारोह के साथ परेशान मत करो, बस जगह में करते हैं। नोट: दूसरी पंक्ति कुछ वीएस संस्करणों के तत्काल विंडो में एक तर्क अपवाद को फेंक देगी।

string s = "Blah";
s = new string(s.ToCharArray().Reverse().ToArray()); 

1
कुछ लोगों ने बिना बताए हर उत्तर (मेरा शामिल) को डाउनवोट करने का समय ले लिया।
मार्सेल वाल्डेज़ ओरोज़्को

यह वास्तव में जगह नहीं है, क्योंकि आप new string
mbadawi23

5

लंबी पोस्ट के लिए खेद है, लेकिन यह दिलचस्प हो सकता है

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        public static string ReverseUsingArrayClass(string text)
        {
            char[] chars = text.ToCharArray();
            Array.Reverse(chars);
            return new string(chars);
        }

        public static string ReverseUsingCharacterBuffer(string text)
        {
            char[] charArray = new char[text.Length];
            int inputStrLength = text.Length - 1;
            for (int idx = 0; idx <= inputStrLength; idx++) 
            {
                charArray[idx] = text[inputStrLength - idx];                
            }
            return new string(charArray);
        }

        public static string ReverseUsingStringBuilder(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }

            StringBuilder builder = new StringBuilder(text.Length);
            for (int i = text.Length - 1; i >= 0; i--)
            {
                builder.Append(text[i]);
            }

            return builder.ToString();
        }

        private static string ReverseUsingStack(string input)
        {
            Stack<char> resultStack = new Stack<char>();
            foreach (char c in input)
            {
                resultStack.Push(c);
            }

            StringBuilder sb = new StringBuilder();
            while (resultStack.Count > 0)
            {
                sb.Append(resultStack.Pop());
            }
            return sb.ToString();
        }

        public static string ReverseUsingXOR(string text)
        {
            char[] charArray = text.ToCharArray();
            int length = text.Length - 1;
            for (int i = 0; i < length; i++, length--)
            {
                charArray[i] ^= charArray[length];
                charArray[length] ^= charArray[i];
                charArray[i] ^= charArray[length];
            }

            return new string(charArray);
        }


        static void Main(string[] args)
        {
            string testString = string.Join(";", new string[] {
                new string('a', 100), 
                new string('b', 101), 
                new string('c', 102), 
                new string('d', 103),                                                                   
            });
            int cycleCount = 100000;

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingCharacterBuffer(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingArrayClass(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingStringBuilder(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingStack(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingXOR(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms");            
        }
    }
}

परिणाम:

  • ReverseUsingCharacterBuffer: 346ms
  • ReverseUsingArrayClass: 87ms
  • ReverseUsingStringBuilder: 824ms
  • ReverseUsingStack: 2086ms
  • ReverseUsingXOR: 319ms

मैंने अपनी पोस्ट में एक समान तुलना जोड़ दी, एक सामुदायिक विकी ताकि आप संपादित करने में सक्षम हों। प्रदर्शन वास्तव में स्ट्रिंग की लंबाई के साथ-साथ एल्गोरिथ्म पर भी निर्भर करता है, इसे ग्राफ बनाना दिलचस्प होगा। मुझे अभी भी लगता है कि Array.Reverse सभी मामलों में सबसे तेज़ होगी ...
सैम केसर

"सभी मामलों में सबसे तेज़ होगा" जब जादुई TrySZReverse फ़ंक्शन (इसका उल्टा कार्यान्वयन में उपयोग किया जाता है) विफल रहता है, Array.Reverse बॉक्सिंग को शामिल करने के लिए सरल कार्यान्वयन में कमियां हैं, इसलिए मेरी विधि जीत जाएगी। हालाँकि मुझे नहीं पता कि TrySZReverse को विफल करने के लिए क्या शर्त है।
एक्यू

सभी मामलों में सबसे तेज़ नहीं है :), मैंने अपनी पोस्ट अपडेट की। यह अभी भी शुद्धता और गति दोनों के लिए यूनिकोड के साथ परीक्षण करने की आवश्यकता है।
सैम केसर

5
public string Reverse(string input)
{
    char[] output = new char[input.Length];

    int forwards = 0;
    int backwards = input.Length - 1;

    do
    {
        output[forwards] = input[backwards];
        output[backwards] = input[forwards];
    }while(++forwards <= --backwards);

    return new String(output);
}

public string DotNetReverse(string input)
{
    char[] toReverse = input.ToCharArray();
    Array.Reverse(toReverse);
    return new String(toReverse);
}

public string NaiveReverse(string input)
{
    char[] outputArray = new char[input.Length];
    for (int i = 0; i < input.Length; i++)
    {
        outputArray[i] = input[input.Length - 1 - i];
    }

    return new String(outputArray);
}    

public string RecursiveReverse(string input)
{
    return RecursiveReverseHelper(input, 0, input.Length - 1);
}

public string RecursiveReverseHelper(string input, int startIndex , int endIndex)
{
    if (startIndex == endIndex)
    {
        return "" + input[startIndex];
    }

    if (endIndex - startIndex == 1)
    {
        return "" + input[endIndex] + input[startIndex];
    }

    return input[endIndex] + RecursiveReverseHelper(input, startIndex + 1, endIndex - 1) + input[startIndex];
}


void Main()
{
    int[] sizes = new int[] { 10, 100, 1000, 10000 };
    for(int sizeIndex = 0; sizeIndex < sizes.Length; sizeIndex++)
    {
        string holaMundo  = "";
        for(int i = 0; i < sizes[sizeIndex]; i+= 5)
        {   
            holaMundo += "ABCDE";
        }

        string.Format("\n**** For size: {0} ****\n", sizes[sizeIndex]).Dump();

        string odnuMaloh = DotNetReverse(holaMundo);

        var stopWatch = Stopwatch.StartNew();
        string result = NaiveReverse(holaMundo);
        ("Naive Ticks: " + stopWatch.ElapsedTicks).Dump();

        stopWatch.Restart();
        result = Reverse(holaMundo);
        ("Efficient linear Ticks: " + stopWatch.ElapsedTicks).Dump();

        stopWatch.Restart();
        result = RecursiveReverse(holaMundo);
        ("Recursive Ticks: " + stopWatch.ElapsedTicks).Dump();

        stopWatch.Restart();
        result = DotNetReverse(holaMundo);
        ("DotNet Reverse Ticks: " + stopWatch.ElapsedTicks).Dump();
    }
}

उत्पादन

आकार के लिए: 10

Naive Ticks: 1
Efficient linear Ticks: 0
Recursive Ticks: 2
DotNet Reverse Ticks: 1

आकार के लिए: 100

Naive Ticks: 2
Efficient linear Ticks: 1
Recursive Ticks: 12
DotNet Reverse Ticks: 1

आकार के लिए: 1000

Naive Ticks: 5
Efficient linear Ticks: 2
Recursive Ticks: 358
DotNet Reverse Ticks: 9

आकार के लिए: 10000

Naive Ticks: 32
Efficient linear Ticks: 28
Recursive Ticks: 84808
DotNet Reverse Ticks: 33

1
खाली स्ट्रिंग की जांच करने की आवश्यकता है Reverse(...)। नहीं तो अच्छा काम।
लारा


4

स्टैक-आधारित समाधान।

    public static string Reverse(string text)
    {
        var stack = new Stack<char>(text);
        var array = new char[stack.Count];

        int i = 0;
        while (stack.Count != 0)
        {
            array[i++] = stack.Pop();
        }

        return new string(array);
    }

या

    public static string Reverse(string text)
    {
        var stack = new Stack<char>(text);
        return string.Join("", stack);
    }

4

एक पुनरावर्ती उदाहरण प्रस्तुत करना था:

private static string Reverse(string str)
{
    if (str.IsNullOrEmpty(str) || str.Length == 1)
        return str;
    else
        return str[str.Length - 1] + Reverse(str.Substring(0, str.Length - 1));
}

1
लंबाई की स्ट्रिंग 0 को संभाला नहीं जाता है
bohdan_trotsenko

यह उपयोगी नहीं है।
user3613932

3

कैसा रहेगा:

    private string Reverse(string stringToReverse)
    {
        char[] rev = stringToReverse.Reverse().ToArray();
        return new string(rev); 
    }

ऊपर अन्य तरीकों के समान कोडपॉइंट मुद्दे हैं और पहले करते समय की तुलना में बहुत धीमा प्रदर्शन करेंगे ToCharArray। LINQ एन्यूमरेटर भी की तुलना में धीमा है Array.Reverse()
हाबिल

3

मैंने Microsoft.VisualBasic.Strings से C # पोर्ट बनाया है । मुझे यकीन नहीं है कि वे इस तरह के उपयोगी कार्यों (वीबी से) सिस्टम के बाहर क्यों रख रहे हैं। फ्रेमवर्क में, लेकिन अभी भी Microsoft.VisualBasic के तहत। वित्तीय कार्यों (जैसे Microsoft.VisualBasic.Financial.Pmt()) के लिए एक ही परिदृश्य ।

public static string StrReverse(this string expression)
{
    if ((expression == null))
        return "";

    int srcIndex;

    var length = expression.Length;
    if (length == 0)
        return "";

    //CONSIDER: Get System.String to add a surrogate aware Reverse method

    //Detect if there are any graphemes that need special handling
    for (srcIndex = 0; srcIndex <= length - 1; srcIndex++)
    {
        var ch = expression[srcIndex];
        var uc = char.GetUnicodeCategory(ch);
        if (uc == UnicodeCategory.Surrogate || uc == UnicodeCategory.NonSpacingMark || uc == UnicodeCategory.SpacingCombiningMark || uc == UnicodeCategory.EnclosingMark)
        {
            //Need to use special handling
            return InternalStrReverse(expression, srcIndex, length);
        }
    }

    var chars = expression.ToCharArray();
    Array.Reverse(chars);
    return new string(chars);
}

///<remarks>This routine handles reversing Strings containing graphemes
/// GRAPHEME: a text element that is displayed as a single character</remarks>
private static string InternalStrReverse(string expression, int srcIndex, int length)
{
    //This code can only be hit one time
    var sb = new StringBuilder(length) { Length = length };

    var textEnum = StringInfo.GetTextElementEnumerator(expression, srcIndex);

    //Init enumerator position
    if (!textEnum.MoveNext())
    {
        return "";
    }

    var lastSrcIndex = 0;
    var destIndex = length - 1;

    //Copy up the first surrogate found
    while (lastSrcIndex < srcIndex)
    {
        sb[destIndex] = expression[lastSrcIndex];
        destIndex -= 1;
        lastSrcIndex += 1;
    }

    //Now iterate through the text elements and copy them to the reversed string
    var nextSrcIndex = textEnum.ElementIndex;

    while (destIndex >= 0)
    {
        srcIndex = nextSrcIndex;

        //Move to next element
        nextSrcIndex = (textEnum.MoveNext()) ? textEnum.ElementIndex : length;
        lastSrcIndex = nextSrcIndex - 1;

        while (lastSrcIndex >= srcIndex)
        {
            sb[destIndex] = expression[lastSrcIndex];
            destIndex -= 1;
            lastSrcIndex -= 1;
        }
    }

    return sb.ToString();
}

+1, एक अच्छा जोड़! मैंने बस इसके साथ कोशिश की string s = "abo\u0327\u0307\u035d\U0001d166cd", जिसमें oBMP में 3 संयुक्ताक्षर चिह्न और उसके बाद सूक्ष्म विमान (गैर-BMP) से एक संयोजन चिह्न (MUSMBOL COMBINING STEM) अक्षर शामिल हैं और यह उन्हें अक्षुण्ण रखता है। लेकिन यह विधि धीमी है यदि इस तरह के पात्र केवल एक लंबी स्ट्रिंग के अंत में दिखाई देते हैं, क्योंकि इसे पूरे सरणी पर दो बार जाना है।
हाबिल

3

इस पुराने सूत्र पर पोस्ट करने के लिए क्षमा करें। मैं एक साक्षात्कार के लिए कुछ कोड का अभ्यास कर रहा हूं।

यह मैं # के लिए आया था। रिफैक्टरिंग से पहले मेरा पहला संस्करण भयानक था।

static String Reverse2(string str)
{
    int strLen = str.Length, elem = strLen - 1;
    char[] charA = new char[strLen];

    for (int i = 0; i < strLen; i++)
    {
        charA[elem] = str[i];
        elem--;
    }

    return new String(charA);
}

Array.Reverseनीचे दी गई विधि के विपरीत , यह 12 वर्णों या स्ट्रिंग में कम के साथ तेजी से प्रकट होता है। 13 वर्णों के बाद, Array.Reverseतेजी से शुरू होता है, और यह अंततः गति पर बहुत अधिक हावी होता है। मैं बस लगभग इंगित करना चाहता था कि गति कहां से शुरू होती है।

static String Reverse(string str)
{     
    char[] charA = str.ToCharArray();

    Array.Reverse(charA);

    return new String(charA);
}

स्ट्रिंग में 100 वर्णों पर, यह मेरे संस्करण x 4 की तुलना में तेज़ है। हालांकि, अगर मुझे पता था कि तार हमेशा 13 वर्णों से कम होंगे, तो मैं अपने द्वारा बनाए गए एक का उपयोग करूंगा।

Stopwatch5000000 पुनरावृत्तियों के साथ परीक्षण किया गया था । इसके अलावा, मुझे यकीन नहीं है कि अगर मेरा संस्करण Unicodeएन्कोडिंग के साथ सरोगेट्स या संयुक्त चरित्र स्थितियों को संभालता है ।


2

"बेहतर तरीका" इस बात पर निर्भर करता है कि आपकी स्थिति, प्रदर्शन, लालित्य, रखरखाव आदि में आपके लिए अधिक महत्वपूर्ण क्या है।

वैसे भी, यहाँ Array.Reverse का उपयोग करने का तरीका है:

string inputString="The quick brown fox jumps over the lazy dog.";
char[] charArray = inputString.ToCharArray(); 
Array.Reverse(charArray); 

string reversed = new string(charArray);

2

अगर यह कभी एक साक्षात्कार में आया और आपको बताया गया कि आप Array.Reverse का उपयोग नहीं कर सकते, तो मुझे लगता है कि यह सबसे तेज़ में से एक हो सकता है। यह नए तार नहीं बनाता है और केवल सरणी के आधे से अधिक पुनरावृत्त करता है (अर्थात O (n / 2) पुनरावृत्तियों)

    public static string ReverseString(string stringToReverse)
    {
        char[] charArray = stringToReverse.ToCharArray();
        int len = charArray.Length-1;
        int mid = len / 2;

        for (int i = 0; i < mid; i++)
        {
            char tmp = charArray[i];
            charArray[i] = charArray[len - i];
            charArray[len - i] = tmp;
        }
        return new string(charArray);
    }

2
मैं बहुत कुछ stringToReverse.ToCharArray () कॉल O (N) निष्पादन समय का उत्पादन करूंगा।
मार्सेल वाल्डेज़ ओरोज़्को

में बिग-ओ अंकन , कारक पर निर्भर नहीं xआपके मामले में, या, n, नहीं किया जाता है। आपके एल्गोरिथ्म में प्रदर्शन है f(x) = x + ½x + C, जहां सी कुछ स्थिर है। चूंकि दोनों Cऔर कारक पर निर्भर नहीं हैं x, इसलिए आपका एल्गोरिथ्म है O(x)। इसका मतलब यह नहीं है कि यह लंबाई के किसी भी इनपुट के लिए तेज़ नहीं होगा x, लेकिन इसका प्रदर्शन रैखिक रूप से इनपुट लंबाई पर निर्भर है। @MarcelValdezOrozco को जवाब देने के लिए, हां, यह भी है O(n), हालांकि यह गति में सुधार के लिए प्रति-बाइट विखंडू प्रति (यह memcpyकुल लंबाई पर एक सीधे उपयोग नहीं करता है ) की नकल करता है ।
हाबिल

2

यदि आपके पास एक स्ट्रिंग है जिसमें केवल ASCII वर्ण हैं, तो आप इस विधि का उपयोग कर सकते हैं।

    public static string ASCIIReverse(string s)
    {
        byte[] reversed = new byte[s.Length];

        int k = 0;
        for (int i = s.Length - 1; i >= 0; i--)
        {
            reversed[k++] = (byte)s[i];
        }

        return Encoding.ASCII.GetString(reversed);
    }

2

सबसे पहले आपको जो समझना है, वह यह है कि str + = 1 अतिरिक्त चार के लिए जगह बनाने के लिए आपकी स्ट्रिंग मेमोरी को आकार देगा। यह ठीक है, लेकिन अगर आपके पास 1000 पृष्ठों वाली पुस्तक है, जिसे आप रिवर्स करना चाहते हैं, तो इसे निष्पादित करने में बहुत लंबा समय लगेगा।

समाधान है कि कुछ लोगों का सुझाव हो सकता है StringBuilder का उपयोग कर रहा है। जब आप एक + प्रदर्शन करते हैं, तो स्ट्रिंग बिल्डर क्या करता है कि यह नए चरित्र को धारण करने के लिए मेमोरी की बहुत बड़ी मात्रा को आवंटित करता है, ताकि हर बार जब आप एक चार को जोड़ते हैं, तो इसे फिर से शुरू करने की आवश्यकता न हो।

यदि आप वास्तव में एक तेज़ और न्यूनतम समाधान चाहते हैं, तो मैं निम्नलिखित सुझाव दूंगा:

            char[] chars = new char[str.Length];
            for (int i = str.Length - 1, j = 0; i >= 0; --i, ++j)
            {
                chars[j] = str[i];
            }
            str = new String(chars);

इस घोल में एक प्रारंभिक मेमोरी आवंटन होता है जब चार [] को इनिशियलाइज़ किया जाता है और एक आवंटन तब होता है जब स्ट्रिंग कंस्ट्रक्टर चार सरणी से स्ट्रिंग का निर्माण करता है।

अपने सिस्टम पर मैंने आपके लिए एक परीक्षण चलाया जो 2 750 000 वर्णों की एक स्ट्रिंग को उलट देता है। यहाँ 10 निष्पादन के लिए परिणाम हैं:

स्ट्रिंगबर्ल: 190K - 200K टिक

चार ऐरे: 130K - 160K टिक

मैंने सामान्य स्ट्रिंग + = के लिए एक परीक्षण भी चलाया लेकिन मैंने इसे 10 मिनट बाद बिना किसी आउटपुट के छोड़ दिया।

हालांकि, मैंने यह भी देखा कि छोटे तारों के लिए स्ट्रिंगब्यूलर तेज है, इसलिए आपको इनपुट के आधार पर कार्यान्वयन के बारे में फैसला करना होगा।

चियर्स


के लिए काम नहीं करता😀Les Misérables
चार्ल्स

@Charles आह हाँ वहाँ चार सेट सीमा है मुझे लगता है।
रियासुरिया

2
public static string reverse(string s) 
{
    string r = "";
    for (int i = s.Length; i > 0; i--) r += s[i - 1];
    return r;
}

1
public static string Reverse2(string x)
        {
            char[] charArray = new char[x.Length];
            int len = x.Length - 1;
            for (int i = 0; i <= len; i++)
                charArray[i] = x[len - i];
            return new string(charArray);
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.