Решение для .NET 7
static void Main(string[] args)
{
string text = string.Concat(Enumerable.Repeat("HelloWorld", 10000000)); // 100M символов
Console.WriteLine(text.Length);
Stopwatch sw = Stopwatch.StartNew();
Console.WriteLine(IsAsciiString(text));
Console.WriteLine(sw.Elapsed);
Console.ReadKey();
}
private static bool IsAsciiString(ReadOnlySpan<char> text)
{
foreach (char c in text)
{
if (!char.IsAsciiLetterOrDigit(c))
return false;
}
return true;
}
В отладке показывает
100000000
True
00:00:00.5075348
В релизе
100000000
True
00:00:00.1745654
А надо ли быстрее? 200 мегабайт данных за 0,1 секунды.
Теперь почистим строку
static void Main(string[] args)
{
string text = string.Concat(Enumerable.Repeat("Hello World!", 10000000)); // 120M символов
Stopwatch sw = Stopwatch.StartNew();
Console.WriteLine(text.Length);
string clean = CleanUpText(text);
Console.WriteLine(clean.Length);
Console.WriteLine(sw.Elapsed);
Console.ReadKey();
}
private static string CleanUpText(ReadOnlySpan<char> text)
{
var sb = new StringBuilder(text.Length < 32 ? text.Length : text.Length / 2);
foreach (char c in text)
{
if (char.IsAsciiLetterOrDigit(c))
sb.Append(c);
}
return sb.ToString();
}
В отладке
120000000
100000000
00:00:00.9601710
в релизе
120000000
100000000
00:00:00.3722909
Быстрее только на векторах. Честно говоря, не особо верю в регулярки в таких примитивных задачах, хотя не исключаю, что векторизованная регулярка может оказаться внезапно быстрее кода, приведенного выше. В .NET 7 их сильно ускорили, и при грамотном использовании можно получить прекрасный результат. Вопрос в том, насколько быстро вам это надо, достаточно того что выше, или же нет.