Best way to reverse a string
Asked Answered
D

53

574

I've just had to write a string reverse function in C# 2.0 (i.e. LINQ not available) and came up with this:

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

Personally I'm not crazy about the function and am convinced that there's a better way to do it. Is there?

Duchamp answered 23/10, 2008 at 0:31 Comment(5)
Surprisingly tricky if you want proper international support. Example: Croatian/Serbian have two-character letters lj, nj etc. Proper reverse of "ljudi" is "idulj", NOT "idujl". I'm sure you'd fare far worse when it comes to Arabic, Thai etc.Incommensurate
I wonder if it's slower to concat a string instead of initializing a temp array and storing the results in that, and then finally converting that to a string?Clupeid
Much newer related thread: Reverse a string with accent chars?Subvention
This question could be improved by defining what you mean by "best". Fastest? Most readable? Most reliable across various edge cases (null checks, multiple languages, etc.)? Most maintainable across versions of C# and .NET?Biofeedback
Why there is no inbuilt direct way to do this simple task?Brena
R
823
public static string Reverse( string s )
{
    char[] charArray = s.ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}
Revolutionize answered 23/10, 2008 at 0:40 Comment(18)
sambo99: It doesn't need to mention unicode: chars in C# are unicode characters, not bytes. Xor may be faster, but apart from being far less readable, that may even be what Array.Reverse() uses internally.Oleander
@Arachnid: Actually, chars in C# are UTF-16 code units; it takes two of them to represent a supplementary character. See jaggersoft.com/csharp_standard/9.4.1.htm.Peag
Yeah sambo99 I suppose you are correct but it's a pretty rare case to use UTF-32. And XOR is only faster for a very small range of values, the correct answer would be to implement different methods for different lengths I suppose. But this is clear and concise which is a benefit in my opinion.Revolutionize
Unicode control characters makes this method useless for non latin character sets. See Jon Skeet explanation, using a sock puppet: codeblog.jonskeet.uk/2009/11/02/… (1/4 the way down), or the video: vimeo.com/7516539Eusebioeusebius
Hope you don't encounter any surrogates or combining characters.Farika
Jon Skeet's code does not work as he says. Les miserables reverses correctly. Skeet fail. Unbelievable.Koenig
@AndreiRinea See my recent comment on the question Reverse a string with accent chars?.Subvention
@CallumRogers: Sorry to nitpick, but it's not "non latin character sets" - many languages are covered in the base 16 bits range (A.K.A "the base multilingual plane" (see here)). These languages include Hebrew, Arabic, and even Chinese and Japanese (surprisingly). It really depends on the use case. For example in my case of reversing Hebrew without Diacritics, the above works just fine.Efflorescence
I found it helpful to create an extension method for the string class from the above. @Revolutionize perhaps you might mention that in the answer for other people to find. using System; public static class StringExtension { public static string Reverse(this string s) { char[] charArray = s.ToCharArray(); Array.Reverse( charArray ); return new string( charArray ); } }Geller
@BradleyGrainger You really should quote what you are replying to. Notice that the person you replied to ("arachnid") has deleted their commentHardie
@CallumRogers You write "Unicode control characters makes this method useless for non latin character sets." <-- what unicode control characters? Your link to jon skeet's article doesn't even mention a word about control characters. He doesn't even say the word 'control'. He's talking about unicode combining characters, such as diacritical marks , they aren't control characters. Things like the french acute accent on the letter 'e'. Control characters are ascii codes 0-31 and 127. Not like the acute accent on an 'e'.Hardie
@CallumRogers Furthermore, as has been pointed out, latin vs non latin characters have absolutely nothing to do with this. "unicode combining characters" can occur both in latin, and other languages that aren't based on latin.Hardie
Can user the LINQ for shorter: return new string(s.Reverse().ToArray());Incursive
This implementation is not Unicode safe. It will work, but could throw exceptions for some unicode characters (suplementary set)Amulet
This is not correct. It breaks when given strings with UTF-16 surrogate pairs.Subjective
I revoked the 4th revision because it's not a succinct version of the original implementation, but an entirely different implementation.Unsecured
not good for Unicode's chars!! Chinese, Greek etc.Barbiebarbieri
Yep, that's right strings are immutable and so his original solution would create a new string each time it's changed in memory.Decasyllable
G
217

Here a solution that properly reverses the string "Les Mise\u0301rables" as "selbare\u0301siM seL". This should render just like selbarésiM seL, not selbaŕesiM seL (note the position of the accent), as would the result of most implementations based on code units (Array.Reverse, etc) or even code points (reversing with special care for surrogate pairs).

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

(And live running example here: https://ideone.com/DqAeMJ)

It simply uses the .NET API for grapheme cluster iteration, which has been there since ever, but a bit "hidden" from view, it seems.

Guideline answered 27/2, 2013 at 12:6 Comment(9)
This fails for some locale dependent stuff, though.Guideline
Mmm. I'm guessing it's still future proof then (assuming it's a limitation of the BCL implementation? Fixes to that will automatically benefit use of these APIs)Identity
It's actually significantly faster to instantiate StringInfo(s), then iterate through SubstringByTextElements(x, 1) and build a new string with a StringBuilder.Disunity
It's a bit strange that you've used Jon Skeet's example that he gave years earlier codeblog.jonskeet.uk/2009/11/02/… Les Misérables (though Jon didn't mention a solution, he just listed issues). Good that you came up with a solution. Maybe Jon skeet invented a time machine, went back to 2009 and posted the problem example that you used in your solution.Hardie
Also, you can make your example much much simpler if you say "lés" (it's 3 letters, and one e, and it's easy to see what's going on). instead of including the word miserables too, as somebody might look at the 'e' there in "miserables" by accident, which also has an 's' on it and on the other side.Hardie
As a sidenote, even this code doesn't support composite emojis, like 👨‍👩‍👧‍👦 and 🧑🏻 .Bleachers
@Bleachers that's a bug you can file, because, yes, it should work for those too. Sounds like the implementation is stuck in an old Unicode version's semantics.Guideline
@R.MartinhoFernandes It is already on coreclr issuesBleachers
Support for composite emojis was added with .NET 5 (learn.microsoft.com/en-us/dotnet/core/compatibility/…)Groggery
D
131

This is turning out to be a surprisingly tricky question.

I would recommend using Array.Reverse for most cases as it is coded natively and it is very simple to maintain and understand.

It seems to outperform StringBuilder in all the cases I tested.

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

There is a second approach that can be faster for certain string lengths which uses 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);
    }

Note If you want to support the full Unicode UTF16 charset read this. And use the implementation there instead. It can be further optimized by using one of the above algorithms and running through the string to clean it up after the chars are reversed.

Here is a performance comparison between the StringBuilder, Array.Reverse and Xor method.

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

Here are the results:

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.

It seems that Xor can be faster for short strings.

Dement answered 23/10, 2008 at 0:31 Comment(4)
That doesn't return a string - you need to wrap this in a call to "new String(...)"Robeson
BTW .. I just had a look at the implementation of Array.Reverse, and its done naitively for chars ... it should be much faster than the StringBuilder option.Dement
Good post, I think I would stick with my answer Array.Reverse not just because it seems to have good performance across string lengths but also because it is concise in the code. lets face it maintenance is half the problem. Also whats the performance penalty of all those using statements.Revolutionize
These methods don't handle strings containing characters outside of the Base Multilingual Plane, i.e., Unicode characters >= U+10000 that are represented with two C# chars. I've posted an answer that handles such strings correctly.Peag
L
90

If you can use LINQ (.NET Framework 3.5+) than following one liner will give you short code. Don't forget to add using System.Linq; to have access to Enumerable.Reverse:

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

Notes:

  • not the fastest version - according to Martin Niederl 5.7 times slower than the fastest choice here.
  • this code as many other options completely ignores all sorts of multi-character combinations, so limit usage to homework assignments and strings which do not contain such characters. See another answer in this question for implementation that correctly handles such combinations.
Latoyalatoye answered 6/4, 2013 at 8:14 Comment(2)
That is around 5.7 times slower than the most upvoted version so i would not recommend using this!Kyrakyriako
When I wrote the original question in 2008 the system I was working on at that time was using C# 2.0 and LINQ wasn't available to me - as per the comment at the beginning of the question.Duchamp
P
52

If the string contains Unicode data (strictly speaking, non-BMP characters) the other methods that have been posted will corrupt it, because you cannot swap the order of high and low surrogate code units when reversing the string. (More information about this can be found on my blog.)

The following code sample will correctly reverse a string that contains non-BMP characters, e.g., "\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);
}
Peag answered 23/10, 2008 at 3:40 Comment(11)
chars in C# are not bytes, they're actual characters. Thus, all of this is totally unnecessary.Oleander
Actually, chars in C# are 16-bit UTF-16 code units; a supplementary character is encoded using two of them, so this is necessary,Peag
For details, see §9.4.1.2 of the C# Language Specification: jaggersoft.com/csharp_standard/9.4.1.htmPeag
It seems like System.String really ought to expose a HereBeDragons property for strings that contain Unicode supplementary characters.Ent
While your solution is better than the others, it does not take combining characters into account.Permission
@SebastianNegraszus: That's correct: this method just reverses the codepoints in the string. Reversing the grapheme clusters would probably be more "useful" overall (but what's the "use" of reversing an arbitrary string in the first place?), but is not easy to implement with just the built-in methods in the .NET Framework.Peag
To detect grapheme clusters CharUnicodeInfo.GetUnicodeCategory gives you most of the info you need (notably detecting combining code points). It will also tell you if the code point is a surrogate, so you don't need to hardcode the code point ranges :-)Pretence
@Richard: The rules for breaking grapheme clusters are a little more complicated than just detecting combining code points; see the documentation on Grapheme Cluster Boundaries in UAX #29 for more information.Peag
Very good info! Does ANYONE have a failing test for the Array.Reverse test? And by test I mean a sample string not a whole unit test... It would really help me (and others) convince different persons about this issue..Koenig
@Andrei try "Les Mise\u0301rables".Guideline
A good and safe alternative to this approach is to use StringInfo.GetTextElementEnumerator, which will automatically take care of surrogate pairs. To also take care of combining characters (of which there can be multiple in a row and each can itself be a surrogate pair), use UnicodeCategory.NonSpacingMark, UnicodeCategory.SpacingCombiningMark and UnicodeCategory.EnclosingMark. Also note that UnicodeCategory.ModifierSymbol can be used for the surrounding characters. Reversing a string is truly not trivial.Kanya
S
32

Ok, in the interest of "don't repeat yourself," I offer the following solution:

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

My understanding is that this implementation, available by default in VB.NET, properly handles Unicode characters.

Smirch answered 7/12, 2011 at 17:6 Comment(3)
This only handles surrogates properly. It messes up combining marks: ideone.com/yikdqX.Guideline
On NET .6 is correctly handling combining marks!Showthrough
Awesome simplicity!Dissert
C
22

Have a look at the wikipedia entry here. They implement the String.Reverse extension method. This allows you to write code like this:

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

They also use the ToCharArray/Reverse combination that other answers to this question suggest. The source code looks like this:

public static string Reverse(this string input)
{
    char[] chars = input.ToCharArray();
    Array.Reverse(chars);
    return new String(chars);
}
Chiquita answered 23/10, 2008 at 0:37 Comment(1)
That's wonderful, except extension methods weren't introduced in c# 2.0.Worriment
L
22

Starting with .NET Core 2.1 there is a new way to reverse a string using the string.Create method.

Note that this solution does not handle Unicode combining characters etc. correctly, as "Les Mise\u0301rables" would be converted to "selbarésiM seL". See the other answers for a better solution.

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

This essentially copies the characters of input to a new string and reverses the new string in-place.

Why is string.Create useful?

When we create a string from an existing array, a new internal array is allocated and the values are copied. Otherwise, it would be possible to mutate a string after its creation (in a safe environment). That is, in the following snippet we have to allocate an array of length 10 twice, one as the buffer and one as the string's internal array.

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

string.Create essentially allows us to manipulate the internal array during creation time of the string. This is, we do not need a buffer anymore and can therefore avoid allocating that one char array.

Steve Gordon has written about it in more detail here. There is also an article on MSDN.

How to use string.Create?

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

The method takes three parameters:

  1. The length of the string to create,
  2. the data you want to use to dynamically create the new string,
  3. and a delegate that creates the final string from the data, where the first parameter points to the internal char array of the new string and the second is the data (state) you passed to string.Create.

Inside the delegate we can specify how the new string is created from the data. In our case, we just copy the characters of the input string to the Span used by the new string. Then we reverse the Span and hence the whole string is reversed.

Benchmarks

To compare my proposed way of reversing a string with the accepted answer, I have written two benchmarks using BenchmarkDotNet.

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

Here are the results on my machine:

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

As you can see, with ReverseWithStringCreate we allocate only half of the memory used by the ReverseWithArray method.

Logarithmic answered 8/7, 2019 at 15:8 Comment(3)
It is much faster than Linq reverseSchaller
I just tried this method on .Net 6 and it returns "selbaŕesiM seL" which seems correct, while the other mentioned Grapheme-method returns "selbarésiM seL" which is incorrect. So it seems that this method is not only correct, but around 100x faster.Clarendon
This is the fastest way to reverse a string I have found yet. It's also so simple and readable.Muirhead
O
19

Greg Beech posted an unsafe option that is indeed as fast as it gets (it's an in-place reversal); but, as he indicated in his answer, it's a completely disastrous idea.

That said, I'm surprised there is so much of a consensus that Array.Reverse is the fastest method. There's still an unsafe approach that returns a reversed copy of a string (no in-place reversal shenanigans) significantly faster than the Array.Reverse method for small strings:

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

Here are some benchmark results.

You can see that the performance gain shrinks and then disappears against the Array.Reverse method as the strings get larger. For small- to medium-sized strings, though, it's tough to beat this method.

Olenolin answered 15/6, 2010 at 18:31 Comment(2)
StackOverflow on large strings.Adlei
@rezomegreldize: Yep, that'll happen ;)Olenolin
R
16

If you want to play a really dangerous game, then this is by far the fastest way there is (around four times faster than the Array.Reverse method). It's an in-place reverse using pointers.

Note that I really do not recommend this for any use, ever (have a look here for some reasons why you should not use this method), but it's just interesting to see that it can be done, and that strings aren't really immutable once you turn on unsafe code.

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;
    }
}
Robeson answered 23/10, 2008 at 2:49 Comment(3)
Im pretty sure this will return incorrect results for utf16 strings, it is really asking trouble :)Dement
Hi you should link to this post on this stackoverflow.com/questions/229346/… , as I said before this is really asking for trouble ...Dement
This may be completely evil and ill-advised (as you yourself concede), but there's still a high-performance way to reverse a string using unsafe code that isn't evil and still beats Array.Reverse in many cases. Take a look at my answer.Olenolin
S
16

The easy and nice answer is using the Extension Method:

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

and here's the output:

string Answer = "12345".Inverse(); // = "54321"
Splashboard answered 18/10, 2014 at 11:29 Comment(4)
Reverse() and ToArray() are in the wrong order in your code sample.Lyndy
What purpose does the @ serve?Septuagesima
@Septuagesima See this link: learn.microsoft.com/en-us/dotnet/csharp/language-reference/… Because 'base' is a keyword in C#, it must be prefixed with @ for the C# compiler to interpret it as an identifier.Mccallum
reverse returns IEnumerable<TSource> which is not a string as implied by writing string Answer = "12345".Inverse(); // = "54321"Decasyllable
R
14

Firstly you don't need to call ToCharArray as a string can already be indexed as a char array, so this will save you an allocation.

The next optimisation is to use a StringBuilder to prevent unnecessary allocations (as strings are immutable, concatenating them makes a copy of the string each time). To further optimise this we pre-set the length of the StringBuilder so it won't need to expand its buffer.

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

Edit: Performance Data

I tested this function and the function using Array.Reverse with the following simple program, where Reverse1 is one function and Reverse2 is the other:

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

It turns out that for short strings the Array.Reverse method is around twice as quick as the one above, and for longer strings the difference is even more pronounced. So given that the Array.Reverse method is both simpler and faster I'd recommend you use that rather than this one. I leave this one up here just to show that it isn't the way you should do it (much to my surprise!)

Robeson answered 23/10, 2008 at 0:38 Comment(1)
Wouldn't storing text.Length in a variable give a little more speed as you are referencing this via an object?News
B
12

Try using Array.Reverse


public string Reverse(string str)
{
    char[] array = str.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}
Bandicoot answered 23/10, 2008 at 0:48 Comment(2)
Fails to handle combining code points amongst many other things.Randee
@MooingDuck I looked up code points. Yes. You are correct. It does not handle code points. It is tough to determine all of the requirements for such a simple looking question. Thanks for the feedbackBandicoot
C
12

"Best" can depend on many things, but here are few more short alternatives ordered from fast to slow:

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̽"  👍
Crinose answered 1/10, 2017 at 18:38 Comment(0)
D
10
public static string Reverse(string input)
{
    return string.Concat(Enumerable.Reverse(input));
}

Of course you can extend string class with Reverse method

public static class StringExtensions
{
    public static string Reverse(this string input)
    {
        return string.Concat(Enumerable.Reverse(input));
    }
}
Dichromic answered 9/4, 2013 at 17:47 Comment(1)
Enumerable.Reverse(input) is equal to input.Reverse()Betweenwhiles
A
7

Sorry for long post, but this might be interesting

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

Results:

  • ReverseUsingCharacterBuffer: 346ms
  • ReverseUsingArrayClass: 87ms
  • ReverseUsingStringBuilder: 824ms
  • ReverseUsingStack: 2086ms
  • ReverseUsingXOR: 319ms
Advisement answered 23/10, 2008 at 1:17 Comment(3)
I added a similar comparison in my post, its a community wiki so you should be able to edit. The performance really depends on the length of the string as well as the algorithm, it would be interesting to graph it. I still think Array.Reverse will be fastest in all cases ...Dement
"will be fastest in all cases" when magical TrySZReverse function (it's used in Reverse implementation) fails, Array.Reverse fallbacks to simple implementation involving boxing, so my method will win. However I don't know what is a condition to make TrySZReverse fail.Advisement
Turns out its not fastest in all cases :), I updated my post. This still needs to be tested with unicode for both correctness and speed.Dement
S
7

Don't bother with a function, just do it in place. Note: The second line will throw an argument exception in the Immediate window of some VS versions.

string s = "Blah";
s = new string(s.ToCharArray().Reverse().ToArray()); 
Sension answered 2/4, 2013 at 0:45 Comment(1)
This is not really in place, since you are creating a new stringVaporization
C
6
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();
    }
}

Output

For size: 10

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

For size: 100

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

For size: 1000

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

For size: 10000

Naive Ticks: 32
Efficient linear Ticks: 28
Recursive Ticks: 84808
DotNet Reverse Ticks: 33
Corpsman answered 8/9, 2012 at 6:3 Comment(1)
Need to check for empty string in Reverse(...). Otherwise, good work.Multilateral
G
5

I've made a C# port from Microsoft.VisualBasic.Strings. I'm not sure why they keep such useful functions (from VB) outside the System.String in Framework, but still under Microsoft.VisualBasic. Same scenario for financial functions (e.g. 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();
}
Gordan answered 30/6, 2014 at 21:31 Comment(1)
+1, a nice addition! I just tried it with string s = "abo\u0327\u0307\u035d\U0001d166cd", which contains the letter o followed by 3 combining diacritical marks in the BMP and one combining mark (MUSICAL SYMBOL COMBINING STEM) from the astral plane (non-BMP) and it keeps them intact. But the method is slow if such characters only appear at the end of a long string, as it has to go twice over the whole array.Kanya
W
5

Simplest way:

string reversed = new string(text.Reverse().ToArray());
Welton answered 6/12, 2018 at 9:37 Comment(0)
D
4

"Better way" depends on what is more important to you in your situation, performance, elegance, maintainability etc.

Anyway, here's an approach using 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);
Dasheen answered 23/10, 2008 at 0:41 Comment(0)
B
4

Had to submit a recursive example:

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));
}
Backgammon answered 23/10, 2008 at 0:53 Comment(1)
string of Length 0 are not handledCharente
A
4

How about:

    private string Reverse(string stringToReverse)
    {
        char[] rev = stringToReverse.Reverse().ToArray();
        return new string(rev); 
    }
Arnelle answered 3/2, 2011 at 19:57 Comment(1)
Has the same codepoint issues as other methods above and will perform much slower than when doing a ToCharArray first. The LINQ enumerator is also way slower than Array.Reverse().Kanya
A
4

Stack-based solution.

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

Or

    public static string Reverse(string text)
    {
        var stack = new Stack<char>(text);
        return string.Join("", stack);
    }
Adlei answered 28/1, 2014 at 18:40 Comment(0)
B
4

Since I like a couple of the answers - one for using string.Create and therefore high performance and low allocation and another for correctness - using the StringInfo class, I decided a combined approach is needed. This is the ultimate string reversal method :)

private static string ReverseString(string str)
    {
        return string.Create(str.Length, str, (chars, state) =>
        {
            var enumerator = StringInfo.GetTextElementEnumerator(state);
            var position = state.Length;
            while (enumerator.MoveNext())
            {
                var cluster = ((string)enumerator.Current).AsSpan();
                cluster.CopyTo(chars.Slice(position - cluster.Length));
                position -= cluster.Length;
            }
        });
    }

There's an even better way using a method of the StringInfo class which skips a lot of string allocations by the Enumerator by returning just the indexes.

private static string ReverseString(string str)
    {
        return string.Create(str.Length, str, (chars, state) =>
        {
            var position = 0;
            var indexes = StringInfo.ParseCombiningCharacters(state); // skips string creation
            var stateSpan = state.AsSpan();
            for (int len = indexes.Length, i = len - 1; i >= 0; i--)
            {
                var index = indexes[i];
                var spanLength = i == len - 1 ? state.Length - index : indexes[i + 1] - index;
                stateSpan.Slice(index, spanLength).CopyTo(chars.Slice(position));
                position += spanLength;
            }
        });
    }

Some benchmarks compared to the LINQ solution:

String length 20:

LINQ                       Mean: 2,355.5 ns   Allocated: 1440 B
string.Create              Mean:   851.0 ns   Allocated:  720 B
string.Create with indexes Mean:   466.4 ns   Allocated:  168 B

String length 450:

LINQ                          Mean: 34.33 us   Allocated: 22.98 KB
string.Create                 Mean:   19.13 us   Allocated: 14.98 KB
string.Create with indexes    Mean:   10.32 us   Allocated: 2.69 KB
Boltonia answered 20/8, 2019 at 15:48 Comment(0)
R
3

If it ever came up in an interview and you were told you can't use Array.Reverse, i think this might be one of the fastest. It does not create new strings and iterates only over half of the array (i.e O(n/2) iterations)

    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);
    }
Redundant answered 16/2, 2012 at 7:21 Comment(2)
I'm pretty certain stringToReverse.ToCharArray() call will produce a O(N) execution time.Corpsman
In Big-O notation, the factor not dependent on x, or in your case, n, is not used. Your algorithm has performance f(x) = x + ½x + C, where C is some constant. Since both C and the factor are not dependent on x, your algorithm is O(x). That does not mean that it won't be faster for any input of length x, but its performance is linearly dependent on the input length. To answer @MarcelValdezOrozco, yes, it is also O(n), though it copies per 16-byte chunks to improve speed (it does not use a straight memcpy on the total length).Kanya
Q
3

Sorry for posting on this old thread. I am practicing some code for an interview.

This was what I came up with for C#. My first version before refactoring was horrible.

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

In Contrast to the Array.Reverse method below, it appears faster with 12 characters or less in the string. After 13 characters, the Array.Reverse starts to get faster, and it eventually dominates pretty heavily on speed. I just wanted to point out approximately where the speed starts to change.

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

    Array.Reverse(charA);

    return new String(charA);
}

At 100 characters in the string, it is faster than my version x 4. However, if I knew that the strings would always be less than 13 characters, I would use the one I made.

Testing was done with Stopwatch and 5000000 iterations. Also, I'm not sure if my version handles Surrogates or combined character situations with Unicode encoding.

Quicklime answered 19/6, 2015 at 11:13 Comment(0)
F
2
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);
        }
Floccule answered 27/4, 2012 at 6:21 Comment(0)
A
2

If you have a string that only contains ASCII characters, you can use this method.

    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);
    }
Adlei answered 29/1, 2014 at 12:19 Comment(0)
W
2

First of all what you have to understand is that str+= will resize your string memory to make space for 1 extra char. This is fine, but if you have, say, a book with 1000 pages that you want to reverse, this will take very long to execute.

The solution that some people might suggest is using StringBuilder. What string builder does when you perform a += is that it allocates much larger chunks of memory to hold the new character so that it does not need to do a reallocation every time you add a char.

If you really want a fast and minimal solution I'd suggest the following:

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

In this solution there is one initial memory allocation when the char[] is initialized and one allocation when the string constructor builds the string from the char array.

On my system I ran a test for you that reverses a string of 2 750 000 characters. Here are the results for 10 executions:

StringBuilder: 190K - 200K ticks

Char Array: 130K - 160K ticks

I also ran a test for normal String += but I abandoned it after 10 minutes with no output.

However, I also noticed that for smaller strings the StringBuilder is faster, so you will have to decide on the implementation based on the input.

Cheers

Worktable answered 9/10, 2014 at 5:51 Comment(1)
@Charles Ah yea there is the char set limitation I suppose.Worktable
F
2
public static string reverse(string s) 
{
    string r = "";
    for (int i = s.Length; i > 0; i--) r += s[i - 1];
    return r;
}
Foyer answered 29/10, 2015 at 11:58 Comment(0)
H
2

If someone asks about string reverse, the intension could be to find out whether you know any bitwise operation like XOR. In C# you have Array.Reverse function, however, you can do using simple XOR operation in few lines of code(minimal)

    public static string MyReverse(string s)
    {
        char[] charArray = s.ToCharArray();
        int bgn = -1;
        int end = s.Length;
        while(++bgn < --end)
        {
            charArray[bgn] ^= charArray[end];
            charArray[end] ^= charArray[bgn];
            charArray[bgn] ^= charArray[end];
        }
        return new string(charArray);
    }
Heel answered 7/10, 2020 at 18:24 Comment(0)
H
2

There are a few correct answers where StringInfo.GetTextElementEnumerator() is being used. Kudos to you!

Now, let's find the most efficient way to use this method. First, most answers involve calling Reverse() and ToArray() which is a big no-no on hot paths. For optimal performance, we want to avoid allocating garbage. E.g. temporary strings, allocators, arrays etc.

Optimized reversal of string

using System.Globalization;

public static class StringExtensions
{
    public static string AsReversed(this string s)
    {
        return string.Create(s.Length, s, (chars, state) =>
        {
            int i = 0;
            var enumerator = StringInfo.GetTextElementEnumerator(s);
            while (enumerator.MoveNext())
            {
                var element = enumerator.GetTextElement();
                i += element.Length;
                element.CopyTo(chars[^i..]);
            }
        });
    }
}

Note that the GetTextElementEnumerator() API contains a bug in .NET Core 3.1 and earlier. Make sure to run .NET 5 or later! Finally, make sure to check out issue #19423 where API improvements are being discussed.

Hookup answered 19/8, 2022 at 15:28 Comment(0)
S
1
private static string Reverse(string str)
        {
            string revStr = string.Empty;
            for (int i = str.Length - 1; i >= 0; i--)
            {
                revStr += str[i].ToString();
            }
            return revStr;
        }

Faster than above method

private static string ReverseEx(string str)
        {
            char[] chrArray = str.ToCharArray();
            int len = chrArray.Length - 1;
            char rev = 'n';
            for (int i = 0; i <= len/2; i++)
            {
                rev = chrArray[i];
                chrArray[i] = chrArray[len - i];
                chrArray[len - i] = rev;
            }
            return new string(chrArray);
        }
Seif answered 21/2, 2013 at 16:9 Comment(0)
C
1
    string original = "Stack Overflow";
    string reversed = new string(original.Reverse().ToArray());
Carlos answered 12/3, 2014 at 19:15 Comment(2)
This is a duplicate of several of the other answers on this page.Alexiaalexin
simplest, one-linerGriqua
S
1

There are various ways to reverse the string, I have shown 3 of them below.

-- Using Array.Reverse function.

 private static string ReverseString1(string text)
    {
        char[] rtext = text.ToCharArray();
        Array.Reverse(rtext);
        return new string(rtext);
    }

-- using string only

  private static string ReverseString2(string text)
    {
        String rtext = "";
        for (int i = text.Length - 1; i >= 0; i--)
        {
            rtext = rtext + text[i];
        }
        return rtext;
    }

-- Using only char array

 public static string ReverseString3(string str)
    {
        char[] chars = str.ToCharArray();
        char[] rchars = new char[chars.Length];
        for (int i = 0, j = str.Length - 1; i < chars.Length; i++, j--)
        {
            rchars[j] = chars[i];
        }
        return new string(rchars);
    }
Surfboat answered 31/5, 2016 at 8:59 Comment(0)
K
1

As simple as this:

string x = "your string";       
string x1 = "";
for(int i = x.Length-1 ; i >= 0; i--)
    x1 += x[i];
Console.WriteLine("The reverse of the string is:\n {0}", x1);

See the output.

Karakoram answered 21/9, 2016 at 17:5 Comment(1)
Please be aware, that using this method you're creating x.Length times a new string object x1 as you're not taking into account the inherent immutability of string.Enough
A
1

here is a unicode safe version of the function, written as an extension that will safely handle unicode. It is close to the marked complete answer, but will not throw exceptions for "Invalid high surrogate character".

public static class StringExtensions
{
    public static string Reverse(this string s)
    {
        var info = new StringInfo(s);
        var charArray = new char[s.Length];
        var teIndices = StringInfo.ParseCombiningCharacters(s).Reverse();

        int j = 0;
        foreach(var i in  teIndices)
        {
            if (char.IsHighSurrogate(s[i]))
            {
                charArray[j] = s[i];
                j++;
                charArray[j] = s[i+1];
            }
            else
            {
                charArray[j] = s[i];
            }
            j++;
        }

        return new string(charArray);

    }
}
Amulet answered 2/11, 2017 at 16:35 Comment(1)
It does not handle combining signs: Reverse("Les Mise\u0301rables") != "selbaresiM seL"Showthrough
A
1

How about use Substring

static string ReverseString(string text)
{
    string sub = "";
    int indexCount = text.Length - 1;
    for (int i = indexCount; i > -1; i--)
    {
        sub = sub + text.Substring(i, 1);
    }
    return sub;
}
Attainment answered 14/2, 2018 at 17:18 Comment(0)
D
1

Using LINQ's Aggregate function

string s = "Karthik U";
s = s.Aggregate(new StringBuilder(), (o, p) => o.Insert(0, p)).ToString();
Dodi answered 24/7, 2019 at 7:2 Comment(1)
This is extremely slow for large strings.Prehensile
K
1

Handles all type of unicode characters

    using System.Globalization;

    public static string ReverseString(this string content) {

        var textElementEnumerator = StringInfo.GetTextElementEnumerator(content);

        var SbBuilder = new StringBuilder(content.Length);

        while (textElementEnumerator.MoveNext()) {
            SbBuilder.Insert(0, textElementEnumerator.GetTextElement());
        }

        return SbBuilder.ToString();
    }
Keitel answered 2/4, 2020 at 17:29 Comment(0)
P
1

Another option using span reverse in System.Memory.

public static string Reverse(string str)
{
    Span<char> span = stackalloc char[str.Length];
    str.AsSpan().CopyTo(span);
    span.Reverse();
    return new String(span);
}
Professional answered 4/4, 2023 at 10:58 Comment(0)
G
0

I was asked a similar question in interview. This was my response, although it is probably not as fast in performance as other answers. My question was phrased as "Make a class that can have a method to print a string backwards":

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

namespace BackwardsTest
{
    class PrintBackwards
    {
        public static void print(string param)
        {
            if (param == null || param.Length == 0)
            {
                Console.WriteLine("string is null");
                return;
            }
            List<char> list = new List<char>();
            string returned = null;
            foreach(char d in param)
            {
                list.Add(d);
            }
            for(int i = list.Count(); i > 0; i--)
            {
                returned = returned + list[list.Count - 1];
                list.RemoveAt(list.Count - 1);
            }
            Console.WriteLine(returned);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            string test = "I want to print backwards";
            PrintBackwards.print(test);
            System.Threading.Thread.Sleep(5000);
        }
    }
}
Gunsel answered 8/9, 2016 at 20:58 Comment(0)
S
0
static void Main(string[] args)
{
    string str = "";
    string reverse = "";
    Console.WriteLine("Enter the value to reverse");
    str = Console.ReadLine();
    int length = 0;
    length = str.Length - 1;
    while(length >= 0)
    {
        reverse = reverse + str[length];
        length--;
    }
    Console.Write("Reverse string is {0}", reverse);
    Console.ReadKey();
}
Schatz answered 26/6, 2019 at 12:17 Comment(0)
B
0
     using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {     
        public static string ReverseString(string str)
        {
            int totalLength = str.Length;
            int iCount = 0;
            string strRev = string.Empty;
            iCount = totalLength;
            while (iCount != 0)
            {
                iCount--;
                strRev += str[iCount]; 
            }
            return strRev;
        }
        static void Main(string[] args)
        {
            string str = "Punit Pandya";
            string strResult = ReverseString(str);
            Console.WriteLine(strResult);
            Console.ReadLine();
        }
    }

  }
Barbed answered 11/7, 2019 at 5:18 Comment(0)
C
0

We can use two pointers one pointing to the start of the string and another to the end of the string. Then swap both ith and jth values each time and increment ith pointer +1 and decrement jth pointer -1.

string s = Console.ReadLine();
Console.WriteLine(s + "\n");
char[] charArray = s.ToCharArray();
int i = 0, j = s.Length - 1;
while (i < j) {
    char temp = charArray[i];
    charArray[i] = charArray[j];
    charArray[j] = temp;
    i++; j--;
}
string ans = new string(charArray);
Console.WriteLine(ans + "\n");
// Input: hello
// Output: olleh
Colet answered 22/3, 2022 at 18:30 Comment(0)
R
-1
string A = null;
//a now is reversed and you can use it
A = SimulateStrReverse.StrReverse("your string");

public static class SimulateStrReverse
{
    public static string StrReverse(string expression)
    {
        if (string.IsNullOrEmpty(expression))
            return string.Empty;

        string reversedString = string.Empty;
        for (int charIndex = expression.Length - 1; charIndex >= 0; charIndex--)
        {
            reversedString += expression[charIndex];
        }
        return reversedString;
    }
}
Recife answered 13/12, 2013 at 10:33 Comment(2)
plz explain the answer :)Sirajuddaula
This is horribly inefficient due to lots of string concatenations. Try using StringBuilder instead.Adlei
T
-1

May be using .NET 6.0 or .NET 7.0 it is shortst way

string name = Console.ReadLine();
Console.WriteLine(string.Join("", name.Reverse().ToArray()));
Topic answered 5/7, 2023 at 12:32 Comment(2)
It is not the shortest way. And why introduce any Console operations when the OP didn't include them? string.Concat(name.Reverse()) is much shorter and cleaner.Cartogram
Using Linq Reverse() extension method on IEnumerable has already been proposed in other answers.Freddiefreddy
G
-2

This is the code used for reverse string

public Static void main(){
    string text = "Test Text";
    Console.Writeline(RevestString(text))
}

public Static string RevestString(string text){
    char[] textToChar = text.ToCharArray();
    string result= string.Empty;
    int length = textToChar .Length;
    for (int i = length; i > 0; --i)
    result += textToChar[i - 1];
    return result;
}
Guaranty answered 14/5, 2018 at 19:33 Comment(2)
Please don't post just a code snippet, describe what the code does and why you selected this particular approach.Luteal
Isn't this basically identical to the code that OP said he was looking for a better way of doing?Threadbare
B
-3

It's very simple

static void Reverse()
    {
        string str = "PankajRawat";
        var arr = str.ToCharArray();
        for (int i = str.Length-1; i >= 0; i--)
        {
            Console.Write(arr[i]);
        }
    }
Beaufert answered 18/5, 2018 at 13:58 Comment(0)
M
-4
public string rev(string str)
{
    if (str.Length <= 0)
        return string.Empty;
    else
        return str[str.Length-1]+ rev(str.Substring(0,str.Length-1));
}
Mandragora answered 13/3, 2010 at 20:2 Comment(1)
It's does it's job, but it's probably the worst way to reverse a string because of String obj MUCH memory allocations and recursion.Acquainted
G
-5

Reverse a String without even using a new string. Lets say

String input  = "Mark Henry";
//Just to convert into char array. One can simply take input in char array.
Char[] array = input.toCharArray(input);
int a = input.length;

for(int i=0; i<(array.length/2 -1) ; i++)
{
    array[i] = array[i] + array[a];
    array[a] = array[i] - array[a];
    array[i] = array[i] - array[a--];
}
Gizela answered 27/11, 2014 at 13:26 Comment(1)
You've not tested this at all.Argal
K
-9

SELECT REVERSE('somestring'); Done.

Koffman answered 14/3, 2014 at 20:32 Comment(1)
Where did the OP say he was coming from SQL? Or what server type? this isn't ANSI SQL..Faustina

© 2022 - 2024 — McMap. All rights reserved.