2013-09-18 3 views
1

У меня есть строка в C#, и я хотел бы отфильтровать (выбросить) все символы, кроме цифр, то есть от 0 до 9. Например, если у меня есть строка типа 5435% $% r3443_ + _ + ** ╥╡ ← ", то выход должен быть 54353443. Как это можно сделать с использованием регулярного выражения или что-то еще в C#?C# Регулярные символы фильтрации выражения

Благодаря

+2

возможно дубликат [Regex для чисел только] (http://stackoverflow.com/questions/273141/regex-for-numbers-only) – Marc

+2

Не совсем дубликат. Другой вопрос касается соответствия строк, состоящих только из чисел. – kiheru

+1

@ user1 - Его не дублирующий вопрос, может быть «похожим». – VVV

ответ

1

CODE:

using System; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.Diagnostics; 

public class Foo 
{ 
    public static void Main() 
    { 
     string s = string.Empty; 
     TimeSpan e; 
     var sw = new Stopwatch(); 

     //REGEX   
     sw.Start(); 
     for(var i = 0; i < 10000; i++) 
     { 
      s = "123213!¤%//)54!!#¤!#%13425"; 
      s = Regex.Replace(s, @"\D", ""); 
     } 
     sw.Stop(); 
     e = sw.Elapsed; 

     Console.WriteLine(s); 
     Console.WriteLine(e); 

     sw.Reset(); 

     //NONE REGEX   
     sw.Start(); 
     for(var i = 0; i < 10000; i++) 
     { 
      s = "123213!¤%//)54!!#¤!#%13425"; 
      s = new string(s.Where(c => char.IsDigit(c)).ToArray()); 
     } 
     sw.Stop(); 
     e = sw.Elapsed; 

     Console.WriteLine(s); 
     Console.WriteLine(e); 
    } 
} 

OUTPUT:

1232135413425 
00:00:00.0564964 
1232135413425 
00:00:00.0107598 

Заключение: Это явно способствует регулярному выражению метод NONE, чтобы решить эту проблему.

+0

благодарит вас за дополнительную информацию bro! – VVV

6

Вот несколько примеров, без регулярных выражений:

var str = "5435%$% r3443_+_+**╥╡←"; 
var result = new string(str.Where(o => char.IsDigit(o)).ToArray()); 
//Or you can make code above slightly more compact, using following syntax: 
var result = new string(str.Where(char.IsDigit).ToArray()); 

Выбирается из строки все, что цифра символов, и создает новую строку, основанную на выборе.

И говорить о скорости.

var sw = new Stopwatch(); 
var str = "5435%$% r3443_+_+**╥╡←"; 
sw.Start(); 
for (int i = 0; i < 100000; i++) 
{  
    var result = new string(str.Where(o => char.IsDigit(o)).ToArray()); 
} 
sw.Stop(); 

Console.WriteLine(sw.ElapsedMilliseconds); // Takes nearly 107 ms 

sw.Reset(); 
sw.Start(); 
for (int i = 0; i < 100000; i++) 
{ 
    var s = Regex.Replace(str, @"\D", ""); 
} 
sw.Stop(); 

Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 600 ms 


sw.Reset(); 
sw.Start(); 
for (int i = 0; i < 100000; i++) 
{ 
    var newstr = String.Join("", str.Where(c => Char.IsDigit(c))); 
} 
sw.Stop(); 

Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 109 ms 

Так регулярное выполнение выражение работает предсказуемо медленно. Присоединение и новая строка дают довольно похожие результаты, также это может сильно зависеть от варианта использования. Я не считаю, что тестирование не выполняется с помощью ручного строкового цикла, это может дать наилучшие результаты.

Обновление. Также существует опция RegexOptions.Compiled для регулярного выражения, предполагалось использование из примера. Но для ясности теста можно сказать, что скомпилированное регулярное выражение дает в примере выше прирост производительности почти 150 мс, который все еще довольно медленный (в 4 раза медленнее, чем другой).

+0

Спасибо, друг! – VVV

6

Вам не нужно регулярное выражение для этого

var newstr = String.Join("", str.Where(c => Char.IsDigit(c))); 
1

Что вы пробовали?

static Regex rxNonDigits = new Regex(@"[^\d]+"); 
public static string StripNonDigits(string s) 
{ 
    return rxNonDigits.Replace(s,"") ; 
} 

Или, вероятно, более эффективный

public static string StripNonDigits(string s) 
{ 
    StringBuilder sb = new StrigBuilder(s.Length) ; 
    foreach (char c in s) 
    { 
    if (!char.IsDigit(c)) continue ; 
    sb.Append(c) ; 
    } 
    return sb.ToString() ; 
} 

Или эквивалент один вкладыш:

public static string StripNonDigits(string s) 
{ 
    return new StringBuilder(s.Length) 
     .Append(s.Where(char.IsDigit).ToArray()) 
     .ToString() 
     ; 
} 

Или, если вы не заботитесь о цифрах другой культуры и заботитесь только о ASCII десятичных цифр, вы могли бы сэкономить [возможно] дорогой поиск и сделать два сравнения:

public static string StripNonDigits(string s) 
{ 
    return new StringBuilder(s.Length) 
     .Append(s.Where(c => c >= '0' && c <= '9').ToArray()) 
     .ToString() 
     ; 
} 

Следует отметить, что решения LINQ почти наверняка требуют создания промежуточного массива (то, что не требуется с использованием StringBuilder. Вы также можете использовать агрегацию LINQ:

s.Where(char.IsDigit).Aggregate(new StringBuilder(s.Length), (sb,c) => sb.Append(c)).ToString() 

Существует больше, чем один способ сделать это!

+0

Спасибо, друг за несколько способов решения проблемы :-). – VVV

1

Вы можете просто сделать следующее: в качестве символа класса [ ] используется оператор кат (^).

var pattern = @"[^0-9]+"; 
var replaced = Regex.Replace("5435%$% r3443_+_+**╥╡←", pattern, ""); 

Выход:

54353443 
+0

Ницца и просто! Благодарю. – VVV

1

^ исключает выражение из вашего матча. Используйте его с \d, который соответствует цифрам 0-9, и ничего не замените.

var cleanString = Regex.Replace("123abc,.é", "^\d", ""); 
+0

все было по-другому! спасибо. – VVV

Смежные вопросы