Удаление нечисловых символов в строке

Ответы:

237

Есть много способов, но это должно сработать (хотя не знаю, как это работает с действительно большими строками):

private static string GetNumbers(string input)
{
    return new string(input.Where(c => char.IsDigit(c)).ToArray());
}
Фредрик Мёрк
источник
21
Вероятно, вам следует использовать, IsDigitа не IsNumber: "Этот метод [ IsNumber] определяет, относится ли a Charк какой-либо числовой категории Юникода. Помимо цифр, числа включают символы, дроби, нижние индексы, надстрочные индексы, римские цифры, числители валют и числа в кружочках. Этот метод в отличие от IsDigitметода, который определяет, является ли Chara десятичной цифрой ". msdn.microsoft.com/en-us/library/yk2b3t2y.aspx
LukeH
2
@TrevorBrooks. Предположим, вы можете просто расширить термины:input.Where(c => char.IsDigit(c) || char.IsWhiteSpace(c))
Фредрик Мерк,
6
Его можно еще упростить до return new string(input.Where(char.IsDigit).ToArray());. Я просто
сделал
2
Хороший ответ. Возможно, вам просто захочется переименовать функцию из GetNumbers в GetDigits ... чтобы прояснить ее намерение.
JTech
2
Также является отличным методом расширения.
Роберто Бонини
61

Похоже, хорошо подходит для регулярного выражения.

var s = "40,595 p.a.";
var stripped = Regex.Replace(s, "[^0-9]", "");

"[^0-9]"можно заменить на, @"\D"но удобочитаемость [^0-9].

Йонас Эльфстрём
источник
1
Я был бы согласен, если вы не против накладных расходов, связанных с регулярными выражениями в .Net
FrankO
4
Из любопытства, каковы накладные расходы на производительность между этим ответом и ответом Фредрика Морка?
Scuba Steve
Это, вероятно, медленнее, но единственный способ узнать - измерить, потому что это зависит от того, как .NET реализует регулярные выражения, как компилируется лямбда-выражение и т. Д.
Йонас Эльфстрём
1
Это более гибко, чем использование IsDigit (), поскольку вы можете добавить '.' в регулярное выражение, если вы хотите разрешить числа с десятичными знаками.
Ричард Мур
10
Я провел простое сравнение Regex и LINQ в строке, состоящей из 100 000 GUID, объединенных вместе (в результате получилась строка из 3 600 000 символов). Регулярное выражение постоянно составляло около полсекунды, тогда как LINQ постоянно находилось в диапазоне 1/10 секунды. Обычно LINQ был в среднем в 5 или более раз быстрее.
Крис Пратт
8

Лучше подойдет метод расширения:

public static string GetNumbers(this string text)
    {
        text = text ?? string.Empty;
        return new string(text.Where(p => char.IsDigit(p)).ToArray());
    }
Эрджан Аян
источник
Я предпочитаю if (text == null) return string.Empty;больше text = text ?? string.Empty;. Таким образом мы не снижаем производительность.
Hooman
6

Используйте любое регулярное выражение, которое захватывает только 0–9, а все остальное отбрасывает. Однако регулярное выражение - это операция, которая в первый раз будет стоить очень дорого. Или сделайте что-то вроде этого:

var sb = new StringBuilder();
var goodChars = "0123456789".ToCharArray();
var input = "40,595";
foreach(var c in input)
{
  if(goodChars.IndexOf(c) >= 0)
    sb.Append(c);
}
var output = sb.ToString();

Что-то вроде этого, я думаю, я еще не компилировал ..

LINQ, как сказал Фредрик, тоже вариант

Онкельборг
источник
4

Другой вариант ...

private static string RemoveNonNumberDigitsAndCharacters(string text)
{
    var numericChars = "0123456789,.".ToCharArray();
    return new String(text.Where(c => numericChars.Any(n => n == c)).ToArray());
}
kernowcode
источник
2
а что насчет отрицательного? (-) Разве минус не должен быть кроме этого?
Seabizkit
3
public static string RemoveNonNumeric(string value) => Regex.Replace(value, "[^0-9]", "");
Патрик Кэрнс
источник
это сработает для меня после того, как я пропущу десятичные знаки.
Джон Лорд
0

Ну вы знаете, что это за цифры: 0123456789, верно? Перемещайте строку посимвольно; если символ - цифра, прикрепите его к концу временной строки, иначе игнорируйте. Для строк C # могут быть доступны другие вспомогательные методы, но это общий подход, который работает везде.

Тим
источник
0

Вот код, использующий регулярные выражения:

string str = "40,595 p.a.";

StringBuilder convert = new StringBuilder();

string pattern = @"\d+";
Regex regex = new Regex(pattern);

MatchCollection matches = regex.Matches(str);

foreach (Match match in matches)
{
convert.Append(match.Groups[0].ToString());
}

int value = Convert.ToInt32(convert.ToString()); 
Dhirschl
источник
Что мне нужно сделать, чтобы Regex работал с этой ошибкой Имя «Regex» не существует в текущем контексте
StevieB
using System.Text.RegularExpressions;
dhirschl
0

Принятый ответ великолепен, однако он не принимает во внимание значения NULL, что делает его непригодным для использования в большинстве сценариев.

Это побудило меня вместо этого использовать эти вспомогательные методы. Первый отвечает на OP, а остальные могут быть полезны для тех, кто хочет сделать наоборот:

    /// <summary>
    /// Strips out non-numeric characters in string, returning only digits
    /// ref.: /programming/3977497/stripping-out-non-numeric-characters-in-string
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the input string numeric part: for example, if input is "XYZ1234A5U6" it will return "123456"</returns>
    public static string GetNumbers(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsDigit(c)).ToArray());
    }

    /// <summary>
    /// Strips out numeric and special characters in string, returning only letters
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the letters contained within the input string: for example, if input is "XYZ1234A5U6~()" it will return "XYZAU"</returns>
    public static string GetLetters(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsLetter(c)).ToArray());
    }

    /// <summary>
    /// Strips out any non-numeric/non-digit character in string, returning only letters and numbers
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the letters contained within the input string: for example, if input is "XYZ1234A5U6~()" it will return "XYZ1234A5U6"</returns>
    public static string GetLettersAndNumbers(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsLetterOrDigit(c)).ToArray());
    }

Для получения дополнительной информации прочтите этот пост в моем блоге.

Darkseal
источник
-1
 var output = new string(input.Where(char.IsNumber).ToArray());
Эмре Севим
источник