Usuwanie znaków nienumerycznych w ciągu


Odpowiedzi:


237

Jest wiele sposobów, ale to powinno wystarczyć (nie wiem jednak, jak to działa z naprawdę dużymi ciągami znaków):

private static string GetNumbers(string input)
{
    return new string(input.Where(c => char.IsDigit(c)).ToArray());
}

21
Prawdopodobnie powinieneś IsDigitraczej użyć niż IsNumber: "Ta metoda [ IsNumber] określa, czy a Charnależy do dowolnej numerycznej kategorii Unicode. Oprócz cyfr, liczby obejmują znaki, ułamki, indeksy dolne, indeksy górne, cyfry rzymskie, liczniki walut i liczby zakreślone. Ta metoda kontrastuje z IsDigitmetodą, która określa, czy a Charjest cyfrą dziesiętną ”. msdn.microsoft.com/en-us/library/yk2b3t2y.aspx
— LukeH

2
@TrevorBrooks Przypuszczam, że możesz po prostu rozszerzyć warunki:input.Where(c => char.IsDigit(c) || char.IsWhiteSpace(c))
— Fredrik Mörk,

6
Można to jeszcze bardziej uprościć return new string(input.Where(char.IsDigit).ToArray());. Po prostu
— sprawiam,

2
Niezła odpowiedź. Warto po prostu rozważyć zmianę nazwy funkcji z „GetNumbers” na „GetDigits” ... aby jasno określić jej zamiar.
— JTech

2
To także świetna metoda przedłużania.
— Roberto Bonini

61

Wygląda na to, że dobrze pasuje do wyrażenia regularnego.

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

"[^0-9]"można zastąpić, @"\D"ale podoba mi się czytelność [^0-9].


1
Zgadzam się, o ile nie
— przeszkadza ci

4
Z ciekawości, jaka jest wydajność między tą odpowiedzią a odpowiedzią Fredrika Morka?
— Scuba Steve

Jest to prawdopodobnie wolniejsze, ale jedynym sposobem na poznanie jest pomiar, ponieważ zależy to od tego, jak .NET implementuje wyrażenia regularne, jak jest kompilowane Lambda Expression i nie tylko.
— Jonas Elfström

1
Jest to bardziej elastyczne niż użycie IsDigit (), ponieważ można dodać „.” znaków do wyrażenia regularnego, jeśli chcesz zezwolić na liczby z miejscami dziesiętnymi.
— Richard Moore

10
Zrobiłem proste porównanie Regex vs. LINQ na ciągu złożonym z 100 000 połączonych identyfikatorów GUID (w wyniku czego powstał ciąg 3 600 000 znaków). Regex był konsekwentnie około pół sekundy, podczas gdy LINQ konsekwentnie znajdował się w 1/10 drugiego zakresu. Zasadniczo LINQ był średnio 5 lub więcej razy szybszy.
— Chris Pratt

8

Metoda rozszerzenia będzie lepszym podejściem:

public static string GetNumbers(this string text)
    {
        text = text ?? string.Empty;
        return new string(text.Where(p => char.IsDigit(p)).ToArray());
    }

Wolę if (text == null) return string.Empty;więcej text = text ?? string.Empty;. W ten sposób nie zmniejszamy wydajności.
— Hooman,

6

Użyj dowolnego wyrażenia regularnego, które przechwytuje tylko 0-9, a resztę odrzuca. Jednak wyrażenie regularne to operacja, która za pierwszym razem będzie dużo kosztować. Lub zrób coś takiego:

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();

Myślę, że coś takiego nie skompilowałem ...

LINQ jest, jak powiedział Fredrik, również opcją


4

Inna opcja ...

private static string RemoveNonNumberDigitsAndCharacters(string text)
{
    var numericChars = "0123456789,.".ToCharArray();
    return new String(text.Where(c => numericChars.Any(n => n == c)).ToArray());
}

2
a co z negatywem? (-) czy minus nie powinien być poza tym?
— Seabizkit

3
public static string RemoveNonNumeric(string value) => Regex.Replace(value, "[^0-9]", "");

to zadziała, gdy pozwolę na ułamki dziesiętne.
— John Lord

0

Wiesz, jakie są cyfry: 0123456789, prawda? Przemierzaj łańcuch znak po znaku; jeśli znak jest cyfrą, przyklej go do końca łańcucha tymczasowego, w przeciwnym razie zignoruj. Mogą istnieć inne metody pomocnika dostępne dla ciągów C #, ale jest to podejście ogólne, które działa wszędzie.


0

Oto kod wykorzystujący wyrażenia regularne:

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()); 

Co muszę zrobić, aby uzyskać Regex Working i ten błąd Nazwa „Regex” nie istnieje w bieżącym kontekście
— StevieB

using System.Text.RegularExpressions;
— dhirschl

0

Przyjęta odpowiedź jest świetna, jednak nie bierze pod uwagę wartości NULL, przez co jest bezużyteczna w większości scenariuszy.

To skłoniło mnie do korzystania z tych metod pomocniczych. Pierwsza odpowiada na PO, podczas gdy inne mogą być przydatne dla tych, którzy chcą zrobić coś odwrotnego:

    /// <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());
    }

Aby uzyskać dodatkowe informacje, przeczytaj ten post na moim blogu.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.