gpt4 book ai didi

c# - 在 C# 中循环访问字符串中单个字符的最快方法是什么?

转载 作者:IT王子 更新时间:2023-10-29 03:48:01 24 4
gpt4 key购买 nike

标题就是问题。以下是我尝试通过研究来回答它。但我不相信我的无知研究,所以我仍然提出问题(在 C# 中迭代​​字符串中的单个字符的最快方法是什么?)。

有时我想一个接一个地循环遍历字符串中的字符,例如在解析嵌套标记时 -- cannot be done with regular expressions .我想知道最快的方法是遍历字符串中的各个字符,尤其是非常大的字符串。

我自己做了很多测试,结果如下。然而,有许多读者对 .NET CLR 和 C# 编译器有更深入的了解,所以我不知道我是否遗漏了一些明显的东西,或者我是否在测试代码中犯了错误。所以我征求你们的集体回应。如果有人了解字符串索引器的实际工作原理,那将非常有帮助。 (它是在幕后编译成其他东西的 C# 语言功能吗?还是 CLR 内置的东西?)。

第一种使用流的方法直接取自线程的已接受答案:how to generate a stream from a string?

测试

longString 是一个 9910 万个字符串,由 89 个 C# 语言规范的纯文本版本组成。显示的结果针对 20 次迭代。在有“启动”时间的地方(例如方法 #3 中隐式创建的数组的第一次迭代),我单独测试了它,例如在第一次迭代后从循环中跳出。

结果

根据我的测试,使用 ToCharArray() 方法将字符串缓存在 char 数组中是遍历整个字符串的最快方法。 ToCharArray() 方法是一项前期费用,后续访问单个字符比内置索引访问器稍快。

                                           milliseconds
---------------------------------
Method Startup Iteration Total StdDev
------------------------------ ------- --------- ----- ------
1 index accessor 0 602 602 3
2 explicit convert ToCharArray 165 410 582 3
3 foreach (c in string.ToCharArray)168 455 623 3
4 StringReader 0 1150 1150 25
5 StreamWriter => Stream 405 1940 2345 20
6 GetBytes() => StreamReader 385 2065 2450 35
7 GetBytes() => BinaryReader 385 5465 5850 80
8 foreach (c in string) 0 960 960 4

更新:根据@Eric 的评论,这里是对更正常的 1.1 M 字符字符串(C# 规范的一个副本)进行 100 次迭代的结果。索引器和 char 数组仍然是最快的,其次是 foreach(char in string),其次是流方法。

                                           milliseconds
---------------------------------
Method Startup Iteration Total StdDev
------------------------------ ------- --------- ----- ------
1 index accessor 0 6.6 6.6 0.11
2 explicit convert ToCharArray 2.4 5.0 7.4 0.30
3 for(c in string.ToCharArray) 2.4 4.7 7.1 0.33
4 StringReader 0 14.0 14.0 1.21
5 StreamWriter => Stream 5.3 21.8 27.1 0.46
6 GetBytes() => StreamReader 4.4 23.6 28.0 0.65
7 GetBytes() => BinaryReader 5.0 61.8 66.8 0.79
8 foreach (c in string) 0 10.3 10.3 0.11

使用的代码(单独测试;为简洁起见一起显示)

//1 index accessor
int strLength = longString.Length;
for (int i = 0; i < strLength; i++) { c = longString[i]; }

//2 explicit convert ToCharArray
int strLength = longString.Length;
char[] charArray = longString.ToCharArray();
for (int i = 0; i < strLength; i++) { c = charArray[i]; }

//3 for(c in string.ToCharArray)
foreach (char c in longString.ToCharArray()) { }

//4 use StringReader
int strLength = longString.Length;
StringReader sr = new StringReader(longString);
for (int i = 0; i < strLength; i++) { c = Convert.ToChar(sr.Read()); }

//5 StreamWriter => StreamReader
int strLength = longString.Length;
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(longString);
writer.Flush();
stream.Position = 0;
StreamReader str = new StreamReader(stream);
while (stream.Position < strLength) { c = Convert.ToChar(str.Read()); }

//6 GetBytes() => StreamReader
int strLength = longString.Length;
MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(longString));
StreamReader str = new StreamReader(stream);
while (stream.Position < strLength) { c = Convert.ToChar(str.Read()); }

//7 GetBytes() => BinaryReader
int strLength = longString.Length;
MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(longString));
BinaryReader br = new BinaryReader(stream, Encoding.Unicode);
while (stream.Position < strLength) { c = br.ReadChar(); }

//8 foreach (c in string)
foreach (char c in longString) { }

接受的答案:

我对@CodeInChaos 和 Ben 的笔记的解读如下:

fixed (char* pString = longString) {
char* pChar = pString;
for (int i = 0; i < strLength; i++) {
c = *pChar ;
pChar++;
}
}

在短字符串上执行 100 次迭代的时间为 4.4 毫秒,标准偏差 < 0.1 毫秒。

最佳答案

有什么理由不包含 foreach 吗?

foreach (char c in text)
{
...
}

顺便问一下,这真的会成为您的性能瓶颈吗?迭代本身在总运行时间中所占的比例是多少?

关于c# - 在 C# 中循环访问字符串中单个字符的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8793762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com