Лучший способ перевернуть строку

Мне только что пришлось написать функцию 9X_c# обратного преобразования строки в C# 2.0 9X_dot-net (т.е. LINQ недоступен), и я придумал следующее:

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

Лично 9X_dot-net я не без ума от этой функции и убежден, что 9X_csharp есть способ сделать это лучше. Есть?

548
3

  • Гораздо более новая связанная тема: [Перевернуть с ...
39
Общее количество ответов: 39

Ответ #1

Ответ на вопрос: Лучший способ перевернуть строку

public static string Reverse( string s ) { char[] charArray = s.ToCharArray(); Array.Reverse( charArray ); return new string( charArray ); } 
9X_visual-c#
773
8

  • sambo99: не нужно упоминать Unicode: символы в C# - это символы Unicode, а не байты. X ...

Ответ #2

Ответ на вопрос: Лучший способ перевернуть строку

Вот решение, которое правильно меняет строку 9X_performance "Les Mise\u0301rables" на "selbare\u0301siM seL". Он должен отображаться так же, как 9X_algorithm selbarésiM seL, а не selbaŕesiM seL (обратите внимание на положение 9X_fast акцента), как результат большинства реализаций, основанных 9X_unicode на кодовых единицах (Array.Reverse и т. Д.) Или даже 9X_c#.net кодовых точках (обращая особое внимание 9X_.net-framework на суррогатные пары).

using System; using System.Collections.Generic; using System.Globalization; using System.Linq; public static class Test { private static IEnumerable 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); } } 

(И живой пример работы 9X_c#.net здесь: https://ideone.com/DqAeMJ)

Он просто использует .NET API for grapheme cluster iteration, который 9X_efficiency существует с тех пор, но, кажется, немного 9X_c#.net «скрыт» от просмотра.

214
4

  • +1 Один из очень немногих правильных ответов, и ** намного ** более элегантный и персп ...

Ответ #3

Ответ на вопрос: Лучший способ перевернуть строку

Это оказался на удивление сложным вопросом.

Я 9X_algorithms бы порекомендовал использовать Array.Reverse 9X_c#.net в большинстве случаев, так как он изначально 9X_.net-framework написан и очень прост в обслуживании и понимании.

Похоже, что 9X_efficiency он превосходит StringBuilder во всех тестируемых 9X_dot-net мной случаях.

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

Есть второй подход, который 9X_c#.net может быть быстрее для строк определенной 9X_unicode длины, например 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); } 

Примечание. Если вы хотите поддерживать 9X_fast полную кодировку Unicode UTF16 read this. И используйте 9X_slow вместо этого реализацию. Его можно дополнительно 9X_dot-net оптимизировать, используя один из описанных 9X_efficiency выше алгоритмов и просматривая строку, чтобы 9X_c#.net очистить ее после того, как символы поменялись 9X_c-sharp местами.

Вот сравнение производительности 9X_slow методов StringBuilder, Array.Reverse и Xor.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace ConsoleApplication4 { class Program { delegate string StringDelegate(string s); static void Benchmark(string description, StringDelegate d, int times, string text) { Stopwatch sw = new Stopwatch(); sw.Start(); for (int j = 0; j < times; j++) { d(text); } sw.Stop(); Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times); } public static string ReverseXor(string s) { char[] charArray = s.ToCharArray(); int len = s.Length - 1; for (int i = 0; i < len; i++, len--) { charArray[i] ^= charArray[len]; charArray[len] ^= charArray[i]; charArray[i] ^= charArray[len]; } return new string(charArray); } public static string ReverseSB(string text) { StringBuilder builder = new StringBuilder(text.Length); for (int i = text.Length - 1; i >= 0; i--) { builder.Append(text[i]); } return builder.ToString(); } public static string ReverseArray(string text) { char[] array = text.ToCharArray(); Array.Reverse(array); return (new string(array)); } public static string StringOfLength(int length) { Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)))); } return sb.ToString(); } static void Main(string[] args) { int[] lengths = new int[] {1,10,15,25,50,75,100,1000,100000}; foreach (int l in lengths) { int iterations = 10000; string text = StringOfLength(l); Benchmark(String.Format("String Builder (Length: {0})", l), ReverseSB, iterations, text); Benchmark(String.Format("Array.Reverse (Length: {0})", l), ReverseArray, iterations, text); Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text); Console.WriteLine(); } Console.Read(); } } } 

Вот 9X_dot-net результаты:

26251 Ticks String Builder (Length: 1) : called 10000 times. 33373 Ticks Array.Reverse (Length: 1) : called 10000 times. 20162 Ticks Xor (Length: 1) : called 10000 times. 51321 Ticks String Builder (Length: 10) : called 10000 times. 37105 Ticks Array.Reverse (Length: 10) : called 10000 times. 23974 Ticks Xor (Length: 10) : called 10000 times. 66570 Ticks String Builder (Length: 15) : called 10000 times. 26027 Ticks Array.Reverse (Length: 15) : called 10000 times. 24017 Ticks Xor (Length: 15) : called 10000 times. 101609 Ticks String Builder (Length: 25) : called 10000 times. 28472 Ticks Array.Reverse (Length: 25) : called 10000 times. 35355 Ticks Xor (Length: 25) : called 10000 times. 161601 Ticks String Builder (Length: 50) : called 10000 times. 35839 Ticks Array.Reverse (Length: 50) : called 10000 times. 51185 Ticks Xor (Length: 50) : called 10000 times. 230898 Ticks String Builder (Length: 75) : called 10000 times. 40628 Ticks Array.Reverse (Length: 75) : called 10000 times. 78906 Ticks Xor (Length: 75) : called 10000 times. 312017 Ticks String Builder (Length: 100) : called 10000 times. 52225 Ticks Array.Reverse (Length: 100) : called 10000 times. 110195 Ticks Xor (Length: 100) : called 10000 times. 2970691 Ticks String Builder (Length: 1000) : called 10000 times. 292094 Ticks Array.Reverse (Length: 1000) : called 10000 times. 846585 Ticks Xor (Length: 1000) : called 10000 times. 305564115 Ticks String Builder (Length: 100000) : called 10000 times. 74884495 Ticks Array.Reverse (Length: 100000) : called 10000 times. 125409674 Ticks Xor (Length: 100000) : called 10000 times. 

Похоже, что Xor может быть быстрее 9X_performance для коротких строк.

130
2

  • Эти методы не обрабатывают строки, содержащие символы вне базовой многоязычной плоскости, то есть символы Unicode> = U + 10000, которые представлены двумя символами C#. Я опубликовал ответ, ко ...

Ответ #4

Ответ на вопрос: Лучший способ перевернуть строку

Если вы можете использовать LINQ (.NET Framework 9X_csharp 3.5+), то следующий один лайнер даст вам 9X_algorithm короткий код. Не забудьте добавить using System.Linq;, чтобы 9X_c# получить доступ к Enumerable.Reverse:

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

Примечания:

  • не самая быстрая версия - согласно Martin Niederl в 5,7 раза медленнее, чем самая быстрая версия здесь.
  • этот код, как и многие другие параметры, полностью игнорирует всевозможные многосимвольные комбинации, поэтому ограничьте использование домашними заданиями и строками, которые не содержат такие символы. См. Другой answer в этом вопросе для реализации, которая правильно обрабатывает такие комбинации.

83
1

  • Не самое быстрое решение, но п ...

Ответ #5

Ответ на вопрос: Лучший способ перевернуть строку

Если строка содержит данные Unicode (строго 9X_csharp говоря, символы, отличные от BMP), другие 9X_fast опубликованные методы повредят ее, потому 9X_c# что вы не можете поменять местами высокие 9X_c-sharp и низкие единицы суррогатного кода при реверсировании 9X_algorithm строки. (Более подробную информацию об этом 9X_c-sharp можно найти на my blog.)

В следующем примере кода 9X_c#.net выполняется обратное преобразование строки, содержащей 9X_algorithms символы, отличные от BMP, например "\ U00010380 9X_csharp \ U00010381" (угаритская буква альпа, угаритская 9X_fast буква бета).

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

51
7

  • @Richard: Правила разбиения кластеров графем немного сложнее, чем просто обнаружение объединения кодовых точек; см. документацию по [Границы кластера графемы] (http://www.unicode.org/repor ...

Ответ #6

Ответ на вопрос: Лучший способ перевернуть строку

Хорошо, в интересах «не повторяться» я предлагаю 9X_unicode следующее решение:

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

Насколько я понимаю, эта 9X_slow реализация, доступная по умолчанию в VB.NET, правильно 9X_slow обрабатывает символы Юникода.

27
1

  • Это правильно обрабатывает только суррогатов. Это мешает совмещать метки: http://ideone.com ...

Ответ #7

Ответ на вопрос: Лучший способ перевернуть строку

Взгляните на статью в Википедии here. Они реализуют 9X_algorithm-design метод расширения String.Reverse. Это позволяет 9X_performance писать такой код:

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

Они также используют комбинацию 9X_c-sharp ToCharArray / Reverse, которую предлагают 9X_fast другие ответы на этот вопрос. Исходный код 9X_performance выглядит так:

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

18
0

Ответ #8

Ответ на вопрос: Лучший способ перевернуть строку

Грег Бич опубликовал опцию unsafe, которая действительно 9X_speed работает настолько быстро, насколько это 9X_dotnet возможно (это реверсирование на месте); но, как 9X_csharp он указал в своем ответе, это a completely disastrous idea.

Тем не менее, я 9X_efficiency удивлен, что многие согласны с тем, что 9X_algorithm Array.Reverse - самый быстрый метод. По-прежнему существует 9X_.net подход unsafe, который возвращает перевернутую 9X_algorithms копию строки (без махинаций разворота на 9X_speed месте) значительно быстрее, чем метод Array.Reverse для небольших строк:

public static unsafe string Reverse(string text) { int len = text.Length; // Why allocate a char[] array on the heap when you won't use it // outside of this method? Use the stack. char* reversed = stackalloc char[len]; // Avoid bounds-checking performance penalties. fixed (char* str = text) { int i = 0; int j = i + len - 1; while (i < len) { reversed[i++] = str[j--]; } } // Need to use this overload for the System.String constructor // as providing just the char* pointer could result in garbage // at the end of the string (no guarantee of null terminator). return new string(reversed, 0, len); } 

Here are some benchmark results.

Вы можете видеть, что 9X_speed прирост производительности уменьшается, а 9X_dotnet затем исчезает для метода Array.Reverse по мере того, как 9X_efficiency строки становятся больше. Однако для струн 9X_algorithm-design малого и среднего размера этот метод сложно 9X_dotnet превзойти.

17
1

  • StackOverflow для больших строк.<p>< ...

Ответ #9

Ответ на вопрос: Лучший способ перевернуть строку

Начиная с .NET Core 2.1 появился новый способ 9X_speed перевернуть строку с помощью метода string.Create.

Обратите внимание, что это решение неправильно обрабатывает комбинированные символы Юникода и т. д., поскольку «Les Mise \ u0301rables» будет преобразовано в «selbarésiM seL». the other answers для лучшего решения.

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

По 9X_dot-net сути, это копирует символы input в новую строку 9X_performance и меняет местами новую строку.

Чем полезен string.Create?

Когда мы создаем 9X_efficiency строку из существующего массива, выделяется 9X_c#.net новый внутренний массив и значения копируются. В 9X_speed противном случае можно было бы изменить 9X_.net-framework строку после ее создания (в безопасной среде). То 9X_dotnet есть в следующем фрагменте мы должны дважды 9X_c#.net выделить массив длиной 10: один в качестве 9X_algorithm-design буфера, а другой - в качестве внутреннего 9X_speed массива строки.

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

string.Create по существу позволяет нам 9X_algorithm манипулировать внутренним массивом во время 9X_c# создания строки. То есть нам больше не нужен 9X_performance буфер, и поэтому мы можем избежать выделения 9X_performance этого единственного массива символов.

Стив 9X_c-sharp Гордон написал об этом более подробно here. Также 9X_c-sharp есть статья на MSDN.

Как использовать string.Create?

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

Метод принимает три параметра:

  1. Длина создаваемой строки,
  2. данные, которые вы хотите использовать для динамического создания новой строки,
  3. и делегат, который создает последнюю строку из данных, где первый параметр указывает на внутренний массив char новой строки, а второй - данные (состояние), которые вы передали в string.Create.

Внутри 9X_visual-c# делегата мы можем указать, как новая строка 9X_dotnet создается из данных. В нашем случае мы просто 9X_performance копируем символы входной строки в Span, используемый 9X_.net-framework новой строкой. Затем мы инвертируем Span, и, следовательно, вся 9X_csharp строка переворачивается.

Тесты

Чтобы сравнить предложенный 9X_c# мной способ обращения строки с принятым 9X_algorithms ответом, я написал два теста с использованием 9X_efficiency 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); } 

Вот результаты на моей машине:

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

Как 9X_performance видите, с помощью ReverseWithStringCreate мы выделяем только половину 9X_c#.net памяти, используемой методом ReverseWithArray.

17
0

Ответ #10

Ответ на вопрос: Лучший способ перевернуть строку

Простой и приятный ответ - использовать 9X_visual-c# метод расширения:

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

и вот результат:

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

16
1

  • @ user5389726598465 См. эту ссылку: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim Поскольку 'base' - это ключевое слово в ...

Ответ #11

Ответ на вопрос: Лучший способ перевернуть строку

Во-первых, вам не нужно вызывать ToCharArray, поскольку 9X_performance строка уже может быть проиндексирована как 9X_.net массив символов, поэтому это сэкономит вам 9X_slow выделение.

Следующая оптимизация заключается 9X_dotnet в использовании StringBuilder для предотвращения ненужных 9X_dotnet выделений (поскольку строки неизменяемы, их 9X_algorithms конкатенация каждый раз создает копию строки). Для 9X_performance дальнейшей оптимизации мы предварительно 9X_algorithm установили длину StringBuilder, чтобы не нужно было расширять 9X_dot-net буфер.

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

Изменить: данные об эффективности

Я протестировал эту функцию и функцию 9X_efficiency с помощью Array.Reverse с помощью следующей простой программы, где 9X_c#.net Reverse1 - одна функция, а Reverse2 - другая:

static void Main(string[] args) { var text = "abcdefghijklmnopqrstuvwxyz"; // pre-jit text = Reverse1(text); text = Reverse2(text); // test var timer1 = Stopwatch.StartNew(); for (var i = 0; i < 10000000; i++) { text = Reverse1(text); } timer1.Stop(); Console.WriteLine("First: {0}", timer1.ElapsedMilliseconds); var timer2 = Stopwatch.StartNew(); for (var i = 0; i < 10000000; i++) { text = Reverse2(text); } timer2.Stop(); Console.WriteLine("Second: {0}", timer2.ElapsedMilliseconds); Console.ReadLine(); } 

Оказывается, для 9X_performance коротких строк метод Array.Reverse примерно в два раза 9X_.net быстрее, чем приведенный выше, а для более 9X_csharp длинных строк разница еще более заметна. Поэтому, учитывая, что 9X_slow метод Array.Reverse проще и быстрее, я бы рекомендовал 9X_algorithms вам использовать его, а не этот. Я оставляю 9X_visual-c# это здесь, чтобы показать, что вы должны 9X_fast это делать не так (к моему большому удивлению!)

14
0

Ответ #12

Ответ на вопрос: Лучший способ перевернуть строку

Если вы хотите сыграть в действительно опасную 9X_csharp игру, то это, безусловно, самый быстрый 9X_unicode способ (примерно в четыре раза быстрее, чем 9X_.net-framework метод Array.Reverse). Это обратный ход с использованием 9X_algorithm-design указателей.

Обратите внимание, что я действительно 9X_dotnet не рекомендую это для любого использования 9X_c-sharp (have a look here for some reasons why you should not use this method), но просто интересно увидеть, что это 9X_.net-framework можно сделать, и что строки на самом деле 9X_speed не являются неизменяемыми после включения 9X_performance небезопасного кода.

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

14
0

Ответ #13

Ответ на вопрос: Лучший способ перевернуть строку

Попробуйте использовать Array.Reverse

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

9X_c#

11
0

Ответ #14

Ответ на вопрос: Лучший способ перевернуть строку

«Лучшее» может зависеть от многих вещей, но 9X_visual-c# вот еще несколько коротких альтернатив, упорядоченных 9X_c# от быстрого к медленному:

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̽" 👍 

11
0

Ответ #15

Ответ на вопрос: Лучший способ перевернуть строку

public static string Reverse(string input) { return string.Concat(Enumerable.Reverse(input)); } 
Конечно, вы можете расширить строковый класс 9X_c# с помощью метода Reverse
public static class StringExtensions { public static string Reverse(this string input) { return string.Concat(Enumerable.Reverse(input)); } } 

              
10
0

Ответ #16

Ответ на вопрос: Лучший способ перевернуть строку

Не беспокойтесь о функции, просто сделайте 9X_c# это на месте. Примечание. Вторая строка 9X_.net вызовет исключение аргумента в окне «Немедленное» некоторых 9X_slow версий VS.

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

7
1

  • Какой-то парень нашел время, чтобы проголосовать против каждого ответа (включая мой), не объяс ...

Ответ #17

Ответ на вопрос: Лучший способ перевернуть строку

Извините за длинный пост, но это может быть 9X_algorithm-design интересно

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 resultStack = new Stack(); foreach (char c in input) { resultStack.Push(c); } StringBuilder sb = new StringBuilder(); while (resultStack.Count > 0) { sb.Append(resultStack.Pop()); } return sb.ToString(); } public static string ReverseUsingXOR(string text) { char[] charArray = text.ToCharArray(); int length = text.Length - 1; for (int i = 0; i < length; i++, length--) { charArray[i] ^= charArray[length]; charArray[length] ^= charArray[i]; charArray[i] ^= charArray[length]; } return new string(charArray); } static void Main(string[] args) { string testString = string.Join(";", new string[] { new string('a', 100), new string('b', 101), new string('c', 102), new string('d', 103), }); int cycleCount = 100000; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < cycleCount; i++) { ReverseUsingCharacterBuffer(testString); } stopwatch.Stop(); Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms"); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < cycleCount; i++) { ReverseUsingArrayClass(testString); } stopwatch.Stop(); Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms"); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < cycleCount; i++) { ReverseUsingStringBuilder(testString); } stopwatch.Stop(); Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms"); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < cycleCount; i++) { ReverseUsingStack(testString); } stopwatch.Stop(); Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms"); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < cycleCount; i++) { ReverseUsingXOR(testString); } stopwatch.Stop(); Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms"); } } } 

Результаты:

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

6
0

Ответ #18

Ответ на вопрос: Лучший способ перевернуть строку

public string Reverse(string input) { char[] output = new char[input.Length]; int forwards = 0; int backwards = input.Length - 1; do { output[forwards] = input[backwards]; output[backwards] = input[forwards]; }while(++forwards <= --backwards); return new String(output); } public string DotNetReverse(string input) { char[] toReverse = input.ToCharArray(); Array.Reverse(toReverse); return new String(toReverse); } public string NaiveReverse(string input) { char[] outputArray = new char[input.Length]; for (int i = 0; i < input.Length; i++) { outputArray[i] = input[input.Length - 1 - i]; } return new String(outputArray); } public string RecursiveReverse(string input) { return RecursiveReverseHelper(input, 0, input.Length - 1); } public string RecursiveReverseHelper(string input, int startIndex , int endIndex) { if (startIndex == endIndex) { return "" + input[startIndex]; } if (endIndex - startIndex == 1) { return "" + input[endIndex] + input[startIndex]; } return input[endIndex] + RecursiveReverseHelper(input, startIndex + 1, endIndex - 1) + input[startIndex]; } void Main() { int[] sizes = new int[] { 10, 100, 1000, 10000 }; for(int sizeIndex = 0; sizeIndex < sizes.Length; sizeIndex++) { string holaMundo = ""; for(int i = 0; i < sizes[sizeIndex]; i+= 5) { holaMundo += "ABCDE"; } string.Format("\n**** For size: {0} ****\n", sizes[sizeIndex]).Dump(); string odnuMaloh = DotNetReverse(holaMundo); var stopWatch = Stopwatch.StartNew(); string result = NaiveReverse(holaMundo); ("Naive Ticks: " + stopWatch.ElapsedTicks).Dump(); stopWatch.Restart(); result = Reverse(holaMundo); ("Efficient linear Ticks: " + stopWatch.ElapsedTicks).Dump(); stopWatch.Restart(); result = RecursiveReverse(holaMundo); ("Recursive Ticks: " + stopWatch.ElapsedTicks).Dump(); stopWatch.Restart(); result = DotNetReverse(holaMundo); ("DotNet Reverse Ticks: " + stopWatch.ElapsedTicks).Dump(); } } 
Вывод
Для размера: 10
Naive Ticks: 1 Efficient linear Ticks: 0 Recursive Ticks: 2 DotNet Reverse Ticks: 1 

Для размера: 100
Naive Ticks: 2 Efficient linear Ticks: 1 Recursive Ticks: 12 DotNet Reverse Ticks: 1 

Для размера: 1000
Naive Ticks: 5 Efficient linear Ticks: 2 Recursive Ticks: 358 DotNet Reverse Ticks: 9 

Для размера: 10000
Naive Ticks: 32 Efficient linear Ticks: 28 Recursive Ticks: 84808 DotNet Reverse Ticks: 33 

9X_c#.net
5
1

  • Необходимо проверить пустую строку в `Revers ...

Ответ #19

Ответ на вопрос: Лучший способ перевернуть строку

Самый простой способ:

string reversed = new string(text.Reverse().ToArray()); 

9X_.net-framework

5
0

Ответ #20

Ответ на вопрос: Лучший способ перевернуть строку

Решение на основе стека

 public static string Reverse(string 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 string(array); } 

Или

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

9X_algorithm

4
0

Ответ #21

Ответ на вопрос: Лучший способ перевернуть строку

Пришлось представить рекурсивный пример:

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

9X_algorithm

3
1

  • строка длины 0 ...

Ответ #22

Ответ на вопрос: Лучший способ перевернуть строку

Как насчет

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

9X_c-sharp

3
0

Ответ #23

Ответ на вопрос: Лучший способ перевернуть строку

Я сделал порт C# из Microsoft.VisualBasic.Strings. Я не уверен, почему 9X_dot-net они хранят такие полезные функции (из VB) вне 9X_dot-net System.String в Framework, но по-прежнему 9X_algorithm в Microsoft.VisualBasic. Тот же сценарий 9X_fast для финансовых функций (например, 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); } ///This routine handles reversing Strings containing graphemes /// GRAPHEME: a text element that is displayed as a single character 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(); } 

3
0

Ответ #24

Ответ на вопрос: Лучший способ перевернуть строку

Приносим извинения за сообщение в этой старой 9X_speed беседе. Я отрабатываю код для собеседования.

Это 9X_algorithm то, что я придумал для C#. Моя первая версия 9X_dotnet до рефакторинга была ужасной.

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

В отличие от 9X_slow метода Array.Reverse ниже, он отображается быстрее, если 9X_c#.net в строке не более 12 символов. После 13 9X_.net символов Array.Reverse начинает ускоряться, и в конечном 9X_dotnet итоге он довольно сильно влияет на скорость. Я 9X_unicode просто хотел примерно указать, где скорость 9X_speed начинает меняться.

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

При 100 символах в строке 9X_dot-net это быстрее, чем в моей версии x 4. Однако, если 9X_speed бы я знал, что строки всегда будут меньше 9X_c#.net 13 символов, я бы использовал тот, который 9X_csharp я сделал.

Тестирование проводилось с использованием 9X_dot-net Stopwatch и 5000000 итераций. Кроме того, я не уверен, обрабатывает 9X_dotnet ли моя версия суррогаты или комбинированные 9X_fast символьные ситуации с кодировкой Unicode.

3
0

Ответ #25

Ответ на вопрос: Лучший способ перевернуть строку

Поскольку мне нравится пара ответов - один 9X_dotnet для использования string.Create и, следовательно, высокой 9X_csharp производительности и низкого распределения, а 9X_algorithm другой для правильности - с использованием 9X_c-sharp класса StringInfo, я решил, что необходим комбинированный 9X_algorithms подход. Это идеальный метод переворота строки 9X_dot-net :)

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

Есть еще лучший способ использовать метод 9X_fast класса StringInfo, который пропускает большое 9X_performance количество выделенных строк перечислителем, возвращая 9X_fast только индексы.

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

Некоторые тесты по сравнению 9X_c-sharp с решением LINQ:

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 

3
0

Ответ #26

Ответ на вопрос: Лучший способ перевернуть строку

«Лучший способ» зависит от того, что для 9X_slow вас важнее в вашей ситуации: производительность, элегантность, ремонтопригодность 9X_c#.net и т. д.

В любом случае, вот подход с использованием 9X_fast Array.Reverse:

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

2
0

Ответ #27

Ответ на вопрос: Лучший способ перевернуть строку

Если это когда-нибудь всплывало на собеседовании, и 9X_algorithm-design вам сказали, что вы не можете использовать 9X_algorithm Array.Reverse, я думаю, что это будет одним 9X_algorithm-design из самых быстрых. Он не создает новых строк 9X_visual-c# и выполняет итерацию только по половине 9X_algorithm-design массива (т.е. O (n / 2) итераций)

 public static string ReverseString(string stringToReverse) { char[] charArray = stringToReverse.ToCharArray(); int len = charArray.Length-1; int mid = len / 2; for (int i = 0; i < mid; i++) { char tmp = charArray[i]; charArray[i] = charArray[len - i]; charArray[len - i] = tmp; } return new string(charArray); } 

2
1

  • Я почти уверен, что вызов stringToReverse.ToCharArray() приведет к ...

Ответ #28

Ответ на вопрос: Лучший способ перевернуть строку

Если у вас есть строка, содержащая только 9X_fast символы ASCII, вы можете использовать этот 9X_speed метод.

 public static string ASCIIReverse(string s) { byte[] reversed = new byte[s.Length]; int k = 0; for (int i = s.Length - 1; i >= 0; i--) { reversed[k++] = (byte)s[i]; } return Encoding.ASCII.GetString(reversed); } 

2
0

Ответ #29

Ответ на вопрос: Лучший способ перевернуть строку

Прежде всего, вы должны понять, что str 9X_fast + = изменит размер вашей строковой памяти, чтобы 9X_algorithms освободить место для 1 дополнительного символа. Это 9X_c#.net нормально, но если у вас есть, скажем, книга 9X_speed с 1000 страницами, которую вы хотите перевернуть, это 9X_visual-c# займет очень много времени.

Некоторые люди 9X_dot-net могут предложить решение с использованием 9X_algorithm StringBuilder. Что делает построитель строк, когда 9X_speed вы выполняете + =, так это то, что он выделяет 9X_c# гораздо большие блоки памяти для хранения 9X_dotnet нового символа, поэтому ему не нужно делать 9X_.net перераспределение каждый раз, когда вы добавляете 9X_c# char.

Если вам действительно нужно быстрое 9X_speed и минимальное решение, я бы предложил следующее:

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

В 9X_algorithm этом решении есть одно начальное выделение 9X_.net памяти при инициализации char [] и одно 9X_dotnet выделение, когда конструктор строки строит 9X_csharp строку из массива char.

В своей системе я 9X_algorithms провел для вас тест, который переворачивает 9X_.net-framework строку из 2 750 000 символов. Вот результаты 9X_csharp 10 казней:

StringBuilder: 190–200 000 тиков

Массив 9X_algorithms символов: 130–160 тыс. тиков

Я также провел 9X_c-sharp тест на нормальный String + =, но отказался 9X_.net-framework от него через 10 минут без каких-либо результатов.

Однако 9X_fast я также заметил, что для меньших строк StringBuilder 9X_fast работает быстрее, поэтому вам придется выбирать 9X_algorithm-design реализацию на основе ввода.

Ура

2
0

Ответ #30

Ответ на вопрос: Лучший способ перевернуть строку

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

Ответ #31

Ответ на вопрос: Лучший способ перевернуть строку

Если кто-то спросит о реверсе строки, цель 9X_csharp может заключаться в том, чтобы узнать, знаете 9X_c#.net ли вы какие-либо побитовые операции, такие 9X_c#.net как XOR. В C# у вас есть функция Array.Reverse, однако 9X_efficiency вы можете выполнить простую операцию XOR 9X_efficiency в нескольких строках кода (минимально)

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

2
0

Ответ #32

Ответ на вопрос: Лучший способ перевернуть строку

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); } 
9X_visual-c#
1
0

Ответ #33

Ответ на вопрос: Лучший способ перевернуть строку

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; } 
Быстрее, чем указано выше
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); } 

9X_fast
1
0

Ответ #34

Ответ на вопрос: Лучший способ перевернуть строку

Существуют различные способы перевернуть 9X_slow строку, я показал три из них ниже.

- Использование 9X_fast функции Array.Reverse.

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

- использовать только 9X_performance строку

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

- Использование только массива символов

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

1
0

Ответ #35

Ответ на вопрос: Лучший способ перевернуть строку

Вот так просто:

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

См. output.

9X_algorithm-design

1
1

  • Имейте в виду, что, используя этот метод, вы создаете x.Length, умножая на новый объект string, x1, так как вы не принимаете во внимание неизменность ...

Ответ #36

Ответ на вопрос: Лучший способ перевернуть строку

это безопасная для Unicode версия функции, написанная 9X_csharp как расширение, которое будет безопасно 9X_speed обрабатывать Unicode. Он близок к отмеченному 9X_c#.net полному ответу, но не создает исключений 9X_performance для «Недопустимый высокий суррогатный символ».

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

1
0

Ответ #37

Ответ на вопрос: Лучший способ перевернуть строку

Как насчет использования подстроки

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

9X_algorithm

1
1

  • может захотеть изменить его на `sub = sub + text.Substring (i, 1);` и вместо запи ...

Ответ #38

Ответ на вопрос: Лучший способ перевернуть строку

Использование функции агрегирования LINQ

string s = "Karthik U"; s = s.Aggregate(new StringBuilder(), (o, p) => o.Insert(0, p)).ToString(); 

9X_algorithms

1
1

  • Это очень медленно для ...

Ответ #39

Ответ на вопрос: Лучший способ перевернуть строку

Обрабатывает все типы символов Юникода

с 9X_speed помощью 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(); } 

1
0