Лучший способ перевернуть строку
Мне только что пришлось написать функцию 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 есть способ сделать это лучше. Есть?
- Гораздо более новая связанная тема: [Перевернуть с ...
Ответ #1
Ответ на вопрос: Лучший способ перевернуть строку
public static string Reverse( string s ) { char[] charArray = s.ToCharArray(); Array.Reverse( charArray ); return new string( charArray ); }
9X_visual-c#
- 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 «скрыт» от просмотра.
- +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 для коротких строк.
- Эти методы не обрабатывают строки, содержащие символы вне базовой многоязычной плоскости, то есть символы 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 в этом вопросе для реализации, которая правильно обрабатывает такие комбинации.
- Не самое быстрое решение, но п ...
Ответ #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); }
- @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 обрабатывает символы Юникода.
- Это правильно обрабатывает только суррогатов. Это мешает совмещать метки: 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); }
Ответ #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 превзойти.
- 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);
Метод принимает три параметра:
- Длина создаваемой строки,
- данные, которые вы хотите использовать для динамического создания новой строки,
- и делегат, который создает последнюю строку из данных, где первый параметр указывает на внутренний массив
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
.
Ответ #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"
- @ 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 это делать не так (к моему большому удивлению!)
Ответ #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; } }
Ответ #13
Ответ на вопрос: Лучший способ перевернуть строку
Попробуйте использовать Array.Reverse
public string Reverse(string str) { char[] array = str.ToCharArray(); Array.Reverse(array); return new string(array); }
9X_c#
Ответ #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̽" 👍
Ответ #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)); } }
Ответ #16
Ответ на вопрос: Лучший способ перевернуть строку
Не беспокойтесь о функции, просто сделайте 9X_c# это на месте. Примечание. Вторая строка 9X_.net вызовет исключение аргумента в окне «Немедленное» некоторых 9X_slow версий VS.
string s = "Blah"; s = new string(s.ToCharArray().Reverse().ToArray());
- Какой-то парень нашел время, чтобы проголосовать против каждого ответа (включая мой), не объяс ...
Ответ #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 мс
Ответ #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
- Необходимо проверить пустую строку в `Revers ...
Ответ #19
Ответ на вопрос: Лучший способ перевернуть строку
Самый простой способ:
string reversed = new string(text.Reverse().ToArray());
9X_.net-framework
Ответ #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
Ответ #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
- строка длины 0 ...
Ответ #22
Ответ на вопрос: Лучший способ перевернуть строку
Как насчет
private string Reverse(string stringToReverse) { char[] rev = stringToReverse.Reverse().ToArray(); return new string(rev); }
9X_c-sharp
Ответ #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(); }
Ответ #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
.
Ответ #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
Ответ #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);
Ответ #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); }
- Я почти уверен, что вызов 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); }
Ответ #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 реализацию на основе ввода.
Ура
Ответ #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
Ответ #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); }
Ответ #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#
Ответ #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
Ответ #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); }
Ответ #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
- Имейте в виду, что, используя этот метод, вы создаете 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); } }
Ответ #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
- может захотеть изменить его на `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
- Это очень медленно для ...
Ответ #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(); }
-
4
-
6
-
12
-
5
-
3
-
1
-
2
-
3
-
10
-
8
-
22
-
20
-
24
-
7
-
27
-
21
-
14
-
16
-
10
-
22
-
8
-
3
-
9
-
5
-
20
-
2
-
12
-
4
-
9
-
9
-
5
-
6
-
12
-
11
-
3
-
5
-
4
-
4
-
6
-
7
-
10
-
7
-
10
-
9
-
3
-
4
-
11
-
3
-
21
-
8