Очистка string от ненужнных char
Подскажите хороший способ очистить string от ненужных char.
Найти эти ненужные символы и удалить из строки.
По сути мне нужны только a-z A-Z 0-9 и может быть ещё какие то символыю например дефис -.
Пока приходит в голову, создать только список подходящих мне char и каждый символ в строке перебирать через этот список и либо удалять из строки, либо оставлять.
Ещё, у той же структуры char есть различне методы Is и можно наверно их использовать.
Как лучше сделать и чтобы быстрее работало ?
Ответы (2 шт):
static void Main(string[] args){
Regex rgx = new Regex(@"[^a-zA-Z0-9]");
Console.WriteLine(rgx.IsMatch(args[0]));
Console.WriteLine(rgx.Replace(args[0], ""));
}
В конструктор регулярного выражения нужно включить все разрешённые символы (в данном случае a-z, A-Z и 0-9). IsMatch показывает, есть ли в строке нежелательные символы, а Replace удаляет их.
Так будет лучше. А нужно ли быстрее? Если это какое-то разовое действие, то быстрее не нужно, а если, скажем, требуется обрабатывать миллионы строк, то нужно отказаться от использования регулярных выражений в пользу работы с символами простыми циклами for (не foreach).
Решение для .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 их сильно ускорили, и при грамотном использовании можно получить прекрасный результат. Вопрос в том, насколько быстро вам это надо, достаточно того что выше, или же нет.