我刚刚在c# 2.0中写了一个字符串反向函数(即LINQ不可用),然后想到了这个:
public string Reverse(string text)
{
char[] cArray = text.ToCharArray();
string reverse = String.Empty;
for (int i = cArray.Length - 1; i > -1; i--)
{
reverse += cArray[i];
}
return reverse;
}
就我个人而言,我并不喜欢这个功能,我相信有更好的方法来实现它。是吗?
抱歉写了这么长时间,但这可能会很有趣
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
public static string ReverseUsingArrayClass(string text)
{
char[] chars = text.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
public static string ReverseUsingCharacterBuffer(string text)
{
char[] charArray = new char[text.Length];
int inputStrLength = text.Length - 1;
for (int idx = 0; idx <= inputStrLength; idx++)
{
charArray[idx] = text[inputStrLength - idx];
}
return new string(charArray);
}
public static string ReverseUsingStringBuilder(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
private static string ReverseUsingStack(string input)
{
Stack<char> resultStack = new Stack<char>();
foreach (char c in input)
{
resultStack.Push(c);
}
StringBuilder sb = new StringBuilder();
while (resultStack.Count > 0)
{
sb.Append(resultStack.Pop());
}
return sb.ToString();
}
public static string ReverseUsingXOR(string text)
{
char[] charArray = text.ToCharArray();
int length = text.Length - 1;
for (int i = 0; i < length; i++, length--)
{
charArray[i] ^= charArray[length];
charArray[length] ^= charArray[i];
charArray[i] ^= charArray[length];
}
return new string(charArray);
}
static void Main(string[] args)
{
string testString = string.Join(";", new string[] {
new string('a', 100),
new string('b', 101),
new string('c', 102),
new string('d', 103),
});
int cycleCount = 100000;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingCharacterBuffer(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingArrayClass(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStringBuilder(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStack(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingXOR(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms");
}
}
}
结果:
ReverseUsingCharacterBuffer: 346毫秒
ReverseUsingArrayClass: 87毫秒
ReverseUsingStringBuilder: 824毫秒
ReverseUsingStack: 2086毫秒
ReverseUsingXOR: 319毫秒
首先,你不需要调用ToCharArray,因为字符串已经可以被索引为char数组,所以这将节省你的分配。
下一个优化是使用StringBuilder来防止不必要的分配(因为字符串是不可变的,连接它们每次都会复制一个字符串)。为了进一步优化这一点,我们预先设置了StringBuilder的长度,这样它就不需要扩展它的缓冲区。
public string Reverse(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
编辑:性能数据
我使用Array测试了这个函数和这个函数。用下面的简单程序进行反向,其中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();
}
事实证明,对于短字符串数组。反向方法大约是上面方法的两倍,对于更长的字符串,差异甚至更明显。已知这个数组。反向法既简单又快,我建议你用那个而不是这个。我把这个留在这里只是为了表明这不是你应该做的方式(让我很惊讶!)
有各种方法来反转字符串,我已经在下面展示了其中的3种。
——使用数组。反向作用。
private static string ReverseString1(string text)
{
char[] rtext = text.ToCharArray();
Array.Reverse(rtext);
return new string(rtext);
}
——只使用字符串
private static string ReverseString2(string text)
{
String rtext = "";
for (int i = text.Length - 1; i >= 0; i--)
{
rtext = rtext + text[i];
}
return rtext;
}
——只使用char数组
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);
}