Самый быстрый способ экранирования символов в строке в C#C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Самый быстрый способ экранирования символов в строке в C#

Сообщение Anonymous »

Мне хотелось бы найти самый быстрый способ заменить все зарезервированные символы в строке их экранированной версией.
Есть два наивных способа, которые спонтанно приходят мне на ум (обратите внимание, что набор зарезервированных символов является лишь примером):
A: Использование словаря поиска и String.Replace
private Dictionary _someEscapeTokens = new Dictionary()
{
{"\t", @"\t"},
{"\n", @"\n"},
{"\r", @"\r"}
};

public string GetEscapedStringByNaiveLookUp(string s)
{
foreach (KeyValuePair escapeToken in _someEscapeTokens.Where(kvp => s.Contains(kvp.Key)))
{
s = s.Replace(escapeToken.Key, escapeToken.Value);
}
return s;
}

B: обход каждого символа в строке
public string GetEscapedStringByTraversingCharArray(string s)
{
char[] chars = s.ToCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.Length; i++)
{
switch (chars)
{
case '\t':
sb.Append(@"\t"); break;
case '\n':
sb.Append(@"\n"); break;
case '\r':
sb.Append(@"\r"); break;
default:
sb.Append(chars); break;
}
}
return sb.ToString();
}

Как я уже тестировал, версия B легко превосходит первую.
Примечание: Я уже рассматривал Regex .Escape, но поскольку набор символов не соответствует моему, он не подходит.
Однако есть ли другие способы решения этой проблемы (с учетом производительности)?< /p>
Дополнительное тестирование
Код см. ниже.
Тестирование проводилось на двух разных системах. ориентирован на .NET Framework 4.0. В любом случае, результаты практически такие же:
Char Array (short string) average time: 38600 ns
Foreach (short string) average time: 26680 ns
Char Array (long string) average time: 48,1 ms
Foreach (long string) average time: 64,2 ms
Char Array (escaping only) average time: 13,6 ms
Foreach (escaping only) average time: 17,3 ms

Это приводит меня к выводу, что версия foreach кажется немного быстрее для коротких строк, но почему-то «падает» для более длинных строк. Однако здесь мы говорим о действительно небольших различиях.
Тестирование кода:
private static void Main(string[] args)
{
//around 700 characters
string shortString = new StackTrace().ToString();
string longString;
string pureEscape;
//loading from a file with 1000000 words http://loremipsum.de/
using (StreamReader sr = new StreamReader(@"C:\users\ekrueger\desktop\LoremIpsum.txt"))
{
longString = sr.ReadToEnd();
}
//text file containing only escapable characters (length ~1000000)
using (StreamReader sr = new StreamReader(@"C:\users\ekrueger\desktop\PureEscape.txt"))
{
pureEscape = sr.ReadToEnd();
}
List timesCharArrayShortString = new List();
List timesForeachShortString = new List();
List timesCharArrayLongString = new List();
List timesForeachLongString = new List();
List timesCharArrayPureEscape = new List();
List timesForeachPureEscape = new List();
Stopwatch sw = new Stopwatch();

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringByTraversingCharArray(shortString);
sw.Stop();
timesCharArrayShortString.Add(sw.Elapsed.TotalMilliseconds * 1000000);
}

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringForeach(shortString);
sw.Stop();
timesForeachShortString.Add(sw.Elapsed.TotalMilliseconds * 1000000);
}

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringByTraversingCharArray(longString);
sw.Stop();
timesCharArrayLongString.Add(sw.ElapsedMilliseconds);
}

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringForeach(longString);
sw.Stop();
timesForeachLongString.Add(sw.ElapsedMilliseconds);
}

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringByTraversingCharArray(pureEscape);
sw.Stop();
timesCharArrayPureEscape.Add(sw.ElapsedMilliseconds);
}

for (int i = 0; i < 10; i++)
{
sw.Restart();
GetEscapedStringForeach(pureEscape);
sw.Stop();
timesForeachPureEscape.Add(sw.ElapsedMilliseconds);
}

Console.WriteLine("Char Array (short string) average time: {0} ns", timesCharArrayShortString.Average());
Console.WriteLine("Foreach (short string) average time: {0} ns", timesForeachShortString.Average());
Console.WriteLine("Char Array (long string) average time: {0} ms", timesCharArrayLongString.Average());
Console.WriteLine("Foreach (long string) average time: {0} ms", timesForeachLongString.Average());
Console.WriteLine("Char Array (escaping only) average time: {0} ms", timesCharArrayPureEscape.Average());
Console.WriteLine("Foreach (escaping only) average time: {0} ms", timesForeachPureEscape.Average());

Console.Read();
}

private static string GetEscapedStringByTraversingCharArray(string s)
{
if (String.IsNullOrEmpty(s))
return s;

char[] chars = s.ToCharArray();
StringBuilder sb = new StringBuilder(s.Length);
for (int i = 0; i < chars.Length; i++)
{
switch (chars)
{
case '\t':
sb.Append(@"\t"); break;
case '\n':
sb.Append(@"\n"); break;
case '\r':
sb.Append(@"\r"); break;
case '\f':
sb.Append(@"\f"); break;
default:
sb.Append(chars); break;
}
}
return sb.ToString();
}

public static string GetEscapedStringForeach(string s)
{
if (String.IsNullOrEmpty(s))
return s;

StringBuilder sb = new StringBuilder(s.Length);
foreach (Char ch in s)
{
switch (ch)
{
case '\t':
sb.Append(@"\t"); break;
case '\n':
sb.Append(@"\n"); break;
case '\r':
sb.Append(@"\r"); break;
default:
sb.Append(ch); break;
}
}
return sb.ToString();
}


Подробнее здесь: https://stackoverflow.com/questions/236 ... in-c-sharp
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»