Meilleur moyen d’inverser une chaîne

J’ai juste dû écrire une fonction inverse de chaîne dans C # 2.0 (c.-à-d. LINQ non disponible) et je suis arrivé avec ceci:

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

Personnellement, je ne suis pas fou de la fonction et je suis convaincu qu’il y a une meilleure façon de le faire. Y a-t-il?

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

Voici une solution qui inverse correctement la chaîne "Les Mise\u0301rables" comme "selbare\u0301siM seL" . Cela devrait ressembler à selbarésiM seL , pas à selbaŕesiM seL (notez la position de l’accent), de même que le résultat de la plupart des implémentations basées sur des unités de code ( Array.Reverse , etc) ou même des points de code ).

 using System; using System.Collections.Generic; using System.Globalization; using System.Linq; public static class Test { private static IEnumerable GraphemeClusters(this ssortingng s) { var enumerator = SsortingngInfo.GetTextElementEnumerator(s); while(enumerator.MoveNext()) { yield return (ssortingng)enumerator.Current; } } private static ssortingng ReverseGraphemeClusters(this ssortingng s) { return ssortingng.Join("", s.GraphemeClusters().Reverse().ToArray()); } public static void Main() { var s = "Les Mise\u0301rables"; var r = s.ReverseGraphemeClusters(); Console.WriteLine(r); } } 

(Et en cours d’exécution exemple ici: https://ideone.com/DqAeMJ )

Il utilise simplement l’ API .NET pour l’itération de grappes de graphèmes , qui existe depuis toujours, mais un peu “caché” de la vue, semble-t-il.

Cela se révèle être une question étonnamment délicate.

Je recommanderais d’utiliser Array.Reverse pour la plupart des cas, car il est codé en mode natif et il est très simple à maintenir et à comprendre.

Il semble surpasser SsortingngBuilder dans tous les cas que j’ai testés.

 public ssortingng Reverse(ssortingng text) { if (text == null) return null; // this was posted by petebob as well char[] array = text.ToCharArray(); Array.Reverse(array); return new Ssortingng(array); } 

Il existe une seconde approche qui peut être plus rapide pour certaines longueurs de chaîne utilisant Xor .

  public static ssortingng ReverseXor(ssortingng 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); } 

Remarque Si vous souhaitez prendre en charge le jeu de caractères UTF16 Unicode complet, lisez ceci . Et utilisez la mise en œuvre à la place. Il peut être optimisé en utilisant l'un des algorithmes ci-dessus et en parcourant la chaîne pour le nettoyer une fois les caractères inversés.

Voici une comparaison des performances entre les méthodes SsortingngBuilder, Array.Reverse et Xor.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace ConsoleApplication4 { class Program { delegate ssortingng SsortingngDelegate(ssortingng s); static void Benchmark(ssortingng description, SsortingngDelegate d, int times, ssortingng 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.ToSsortingng(); } public static ssortingng ReverseArray(ssortingng text) { char[] array = text.ToCharArray(); Array.Reverse(array); return (new ssortingng(array)); } public static ssortingng SsortingngOfLength(int length) { Random random = new Random(); SsortingngBuilder sb = new SsortingngBuilder(); 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(); } } } 

Voici les résultats:

 26251 Ticks Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng 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 Ssortingng Builder (Length: 100000) : called 10000 times. 74884495 Ticks Array.Reverse (Length: 100000) : called 10000 times. 125409674 Ticks Xor (Length: 100000) : called 10000 times. 

Il semble que Xor puisse être plus rapide pour les chaînes courtes.

Si la chaîne contient des données Unicode (à proprement parler, des caractères non-BMP), les autres méthodes qui ont été publiées la corrompent, car vous ne pouvez pas échanger l’ordre des unités de code de substitution haute et basse lors de l’inversion de la chaîne. (Plus d’informations à ce sujet peuvent être trouvées sur mon blog .)

L’exemple de code suivant inversera correctement une chaîne qui contient des caractères non-BMP, par exemple, “\ U00010380 \ U00010381” (Ugaritic Letter Alpa, Ugaritic Letter Beta).

 public static ssortingng Reverse(this ssortingng 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); } 

De plus haut 3.5 Framework

 public ssortingng ReverseSsortingng(ssortingng srtVarable) { return new ssortingng(srtVarable.Reverse().ToArray()); } 

Ok, dans l’intérêt de “ne te répète pas”, je propose la solution suivante:

 public ssortingng Reverse(ssortingng text) { return Microsoft.VisualBasic.Ssortingngs.StrReverse(text); } 

Je crois comprendre que cette implémentation, disponible par défaut dans VB.NET, gère correctement les caractères Unicode.

Greg Beech a affiché une option unsafe qui est en effet aussi rapide que possible (c’est un renversement sur place); mais, comme il l’a indiqué dans sa réponse, c’est une idée totalement désastreuse .

Cela dit, je suis surpris qu’il y ait tant de consensus que Array.Reverse est la méthode la plus rapide. Il existe toujours une approche unsafe qui renvoie une copie inversée d’une chaîne (pas de Array.Reverse inversion sur place) beaucoup plus rapide que la méthode Array.Reverse pour les petites chaînes:

 public static unsafe ssortingng Reverse(ssortingng 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); } 

Voici quelques résultats de référence .

Vous pouvez voir que le gain de performance diminue et disparaît ensuite avec la méthode Array.Reverse lorsque les chaînes deviennent plus grandes. Pour les petites et moyennes chaînes, il est difficile de battre cette méthode.

La solution facile et agréable utilise la méthode d’extension:

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

et voici la sortie:

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

Si vous voulez jouer à un jeu vraiment dangereux, c’est de loin le moyen le plus rapide (environ quatre fois plus rapide que la méthode Array.Reverse ). C’est un retour sur place utilisant des pointeurs.

Notez que je ne le recommande vraiment pas pour quelque usage que ce soit ( regardez ici quelques raisons pour lesquelles vous ne devriez pas utiliser cette méthode ), mais il est intéressant de voir que cela peut être fait et que les chaînes ne sont pas immuables une fois que vous activez le code dangereux.

 public static unsafe ssortingng Reverse(ssortingng text) { if (ssortingng.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; } } 

Tout d’abord, vous n’avez pas besoin d’appeler ToCharArray car une chaîne peut déjà être indexée en tant que tableau de caractères, ce qui vous évitera une allocation.

L’optimisation suivante consiste à utiliser un SsortingngBuilder pour empêcher les allocations inutiles (comme les chaînes sont immuables, leur concaténation crée une copie de la chaîne à chaque fois). Pour optimiser cela, nous avons prédéfini la longueur du SsortingngBuilder afin qu’il SsortingngBuilder pas besoin d’étendre son tampon.

 public ssortingng Reverse(ssortingng text) { if (ssortingng.IsNullOrEmpty(text)) { return text; } SsortingngBuilder builder = new SsortingngBuilder(text.Length); for (int i = text.Length - 1; i >= 0; i--) { builder.Append(text[i]); } return builder.ToSsortingng(); } 

Modifier: données de performance

J’ai testé cette fonction et la fonction en utilisant Array.Reverse avec le programme simple suivant, où Reverse1 est une fonction et Reverse2 est l’autre:

 static void Main(ssortingng[] 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(); } 

Il s'avère que pour les chaînes courtes, la méthode Array.Reverse est environ deux fois plus rapide que celle ci-dessus, et pour les chaînes plus longues, la différence est encore plus prononcée. Donc, étant donné que la méthode Array.Reverse est à la fois plus simple et plus rapide, je vous recommande d’utiliser celle-ci plutôt que celle-ci. Je laisse celui-ci ici juste pour montrer que ce n'est pas la façon dont vous devriez le faire (à ma grande surprise!)

Jetez un coup d’œil à l’entrée Wikipédia ici . Ils implémentent la méthode d’extension Ssortingng.Reverse. Cela vous permet d’écrire du code comme ceci:

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

Ils utilisent également la combinaison ToCharArray / Reverse que d’autres réponses à cette question suggèrent. Le code source ressemble à ceci:

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

Essayez d’utiliser Array.Reverse

 public ssortingng Reverse(ssortingng str) { char[] array = str.ToCharArray(); Array.Reverse(array); return new ssortingng(array); } 
 public static ssortingng Reverse(ssortingng input) { return ssortingng.Concat(Enumerable.Reverse(input)); } 

Bien sûr, vous pouvez étendre la classe de chaîne avec la méthode Reverse

 public static class SsortingngExtensions { public static ssortingng Reverse(this ssortingng input) { return ssortingng.Concat(Enumerable.Reverse(input)); } } 

Ne vous embêtez pas avec une fonction, faites-le simplement en place. Remarque: La deuxième ligne lancera une exception d’argument dans la fenêtre Immédiat de certaines versions de VS.

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

J’ai dû soumettre un exemple récursif:

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

Désolé pour le long post, mais cela pourrait être intéressant

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace ConsoleApplication1 { class Program { public static ssortingng ReverseUsingArrayClass(ssortingng text) { char[] chars = text.ToCharArray(); Array.Reverse(chars); return new ssortingng(chars); } public static ssortingng ReverseUsingCharacterBuffer(ssortingng 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.ToSsortingng(); } private static ssortingng ReverseUsingStack(ssortingng input) { Stack resultStack = new Stack(); foreach (char c in input) { resultStack.Push(c); } SsortingngBuilder sb = new SsortingngBuilder(); while (resultStack.Count > 0) { sb.Append(resultStack.Pop()); } return sb.ToSsortingng(); } public static ssortingng ReverseUsingXOR(ssortingng 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"); } } } 

Résultats:

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

Solution basée sur stack.

  public static ssortingng Reverse(ssortingng text) { var stack = new Stack(text); var array = new char[stack.Count]; int i = 0; while (stack.Count != 0) { array[i++] = stack.Pop(); } return new ssortingng(array); } 

Ou

  public static ssortingng Reverse(ssortingng text) { var stack = new Stack(text); return ssortingng.Join("", stack); } 

Que diriez-vous:

  private ssortingng Reverse(ssortingng ssortingngToReverse) { char[] rev = ssortingngToReverse.Reverse().ToArray(); return new ssortingng(rev); } 
 public ssortingng Reverse(ssortingng 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(); } } 

Sortie

Pour la taille: 10

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

Pour la taille: 100

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

Pour taille: 1000

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

Pour la taille: 10000

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

J’ai créé un port C # à partir de Microsoft.VisualBasic.Ssortingngs . Je ne sais pas pourquoi ils conservent de telles fonctions utiles (à partir de VB) en dehors de System.Ssortingng dans Framework, mais toujours sous Microsoft.VisualBasic. Même scénario pour les fonctions financières (par exemple Microsoft.VisualBasic.Financial.Pmt() ).

 public static ssortingng StrReverse(this ssortingng expression) { if ((expression == null)) return ""; int srcIndex; var length = expression.Length; if (length == 0) return ""; //CONSIDER: Get System.Ssortingng 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); } ///This routine handles reversing Ssortingngs containing graphemes /// GRAPHEME: a text element that is displayed as a single character private static ssortingng InternalStrReverse(ssortingng expression, int srcIndex, int length) { //This code can only be hit one time var sb = new SsortingngBuilder(length) { Length = length }; var textEnum = SsortingngInfo.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.ToSsortingng(); } 

“Le meilleur” peut dépendre de beaucoup de choses, mais voici quelques alternatives plus courtes commandées du rapide au lent:

 ssortingng 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 => SsortingngInfo.GetNextTextElement(s, i))); // "😆😀o̓g̈l͘a̎z̽" 👍 ssortingng s4 = Regex.Replace(s, pattern, "$2").Remove(s.Length); // "😆😀o̓g̈l͘a̎z̽" 👍 

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

 ssortingng inputSsortingng="The quick brown fox jumps over the lazy dog."; char[] charArray = inputSsortingng.ToCharArray(); Array.Reverse(charArray); ssortingng reversed = new ssortingng(charArray); 

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

  public static ssortingng ASCIIReverse(ssortingng 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.GetSsortingng(reversed); } 

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 Ssortingng Reverse2(ssortingng 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 ssortingng. 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 Ssortingng Reverse(ssortingng str) { char[] charA = str.ToCharArray(); Array.Reverse(charA); return new Ssortingng(charA); } 

At 100 characters in the ssortingng, it is faster than my version x 4. However, if I knew that the ssortingngs 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.

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

As simple as this:

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

See the output .

How about use Subssortingng

 static ssortingng ReverseSsortingng(ssortingng text) { ssortingng sub = ""; int indexCount = text.Length - 1; for (int i = indexCount; i > -1; i--) { sub = sub + text.Subssortingng(i, 1); } return sub; } 

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 ssortingngs and iterates only over half of the array (ie O(n/2) iterations)

  public static ssortingng ReverseSsortingng(ssortingng ssortingngToReverse) { char[] charArray = ssortingngToReverse.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); } 
 public static ssortingng Reverse2(ssortingng 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); } 
 private static ssortingng Reverse(ssortingng str) { ssortingng revStr = ssortingng.Empty; for (int i = str.Length - 1; i >= 0; i--) { revStr += str[i].ToSsortingng(); } return revStr; } 

Faster than above method

 private static ssortingng ReverseEx(ssortingng 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); }