숫자가 아닌 문자열을 빈 문자열로 교체


125

우리 프로젝트의 요구 사항에 대한 빠른 추가. 전화 번호를 보유 할 DB의 필드는 10 자만 허용하도록 설정되어 있습니다. 따라서 "(913) -444-5555"또는 기타 다른 항목을 전달받는 경우 허용 할 문자 세트를 전달할 수있는 특수 대체 기능을 통해 문자열을 실행하는 빠른 방법이 있습니까?

정규식?

답변:


251

확실히 정규식 :

string CleanPhone(string phone)
{
    Regex digitsOnly = new Regex(@"[^\d]");   
    return digitsOnly.Replace(phone, "");
}

또는 클래스 내에서 항상 정규 표현식을 다시 작성하지 않으려면 다음을 수행하십시오.

private static Regex digitsOnly = new Regex(@"[^\d]");   

public static string CleanPhone(string phone)
{
    return digitsOnly.Replace(phone, "");
}

실제 입력에 따라 선행 1 (장거리) 또는 x 또는 X 뒤에 오는 것 (확장자)을 제거하는 등의 추가 논리가 필요할 수 있습니다.


저건 완벽 해. 이것은 두 번만 사용되므로 클래스를 만들 필요가 없으며 선행 1까지는 나쁜 생각이 아닙니다. 그러나 적어도이 프로젝트에서는 사례별로 처리하는 것이 좋습니다. 다시 한 번 감사드립니다. 다시 투표 할 수 있다면 가능합니다.
매트 도디

1
누군가가 문자열 클래스에 대한 확장 메소드 버전을 게시하기를 기다리고 있습니다 :)
Joel Coehoorn

@Joel 아래 확장 방법 버전을 추가했습니다. 댓글이 마크 다운을 지원하지 않는 것 같아요.
Aaron

13
참고 [^\d]로 단순화 할 수있다\D
pswg

이 답변 (클래스에서 정규 표현식 캐싱)을 아래의 확장 방법과 결합했습니다 :)
Vincent Vancalbergh

73

정규식으로 쉽게 할 수 있습니다.

string subject = "(913)-444-5555";
string result = Regex.Replace(subject, "[^0-9]", ""); // result = "9134445555"

2
훌륭한 답변으로 찬성했지만 Joel은 당신을 이겼습니다. 그래도 답변 주셔서 감사합니다-나는 여러 출처의 확인을 정말로보고 싶습니다.
매트 도디

@JoSmo 공정하게, Joel 's는 사소하게 하나의 라이너로 변환 될 수 있습니다. (그러나 나는 또한 upvoted : D)
Mage Xy

40

정규식을 사용할 필요가 없습니다.

phone = new String(phone.Where(c => char.IsDigit(c)).ToArray())

3
좋은 답변, 왜 RegularExpressions 네임 스페이스에 대한 참조를 추가해야합니까
BTE

1
@BTE 단순히 이용하는 것 짧은 손 때문에system.linq;
에릭 Milliot - 마르티네즈를

1
이것은 정규식 솔루션과 비교하여 얼마나 잘 수행됩니까?
Shavais

2
LINQ 솔루션에 대한 @ Max-PC의 벤치 마크 코드에 테스트를 추가하면 StringBuilder : 273ms, Regex : 2096ms, LINQ : 658ms가됩니다. StringBuilder보다 느리지 만 여전히 Regex보다 훨씬 빠릅니다. 그것이 1,000,000 개의 교체를 벤치마킹하고 있다는 점을 감안할 때, 대부분의 시나리오에서 StringBuilder와 LINQ 솔루션 간의 효과적인 차이는 무시할 수 있습니다.
Chris Pratt

정규식에 대한 @ChrisPratt, 매번 새로운 정규식을 만들었습니까, 아니면 기존 정규식을 재사용하셨습니까? 이는 성능에 큰 영향을 줄 수 있습니다.
carlin.scott

23

확장 방법은 다음과 같습니다.

public static class Extensions
{
    public static string ToDigitsOnly(this string input)
    {
        Regex digitsOnly = new Regex(@"[^\d]");
        return digitsOnly.Replace(input, "");
    }
}

8

.NET에서 Regex 메소드를 사용하면 다음과 같이 \ D를 사용하여 숫자가 아닌 숫자를 일치시킬 수 있습니다.

phoneNumber  = Regex.Replace(phoneNumber, "\\D", String.Empty);

5
이것은 옳지 않습니다. 정규식에서 \를 이스케이프하려면 @ 또는 "\\ D"가 필요합니다. 또한 ""대신 String.Empty를 사용해야합니다.
Bryan

5

정규식을 사용하지 않는 확장 방법은 어떻습니까?

정규식 옵션 중 하나를 고수하면 적어도 RegexOptions.Compiled정적 변수에 사용 하십시오.

public static string ToDigitsOnly(this string input)
{
    return new String(input.Where(char.IsDigit).ToArray());
}

이는 메소드 그룹으로 변환 된 Usman Zafar의 답변을 기반으로합니다.


4

최상의 성능과 낮은 메모리 소비를 위해 다음을 시도하십시오.

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

public class Program
{
    private static Regex digitsOnly = new Regex(@"[^\d]");

    public static void Main()
    {
        Console.WriteLine("Init...");

        string phone = "001-12-34-56-78-90";

        var sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 1000000; i++)
        {
            DigitsOnly(phone);
        }
        sw.Stop();
        Console.WriteLine("Time: " + sw.ElapsedMilliseconds);

        var sw2 = new Stopwatch();
        sw2.Start();
        for (int i = 0; i < 1000000; i++)
        {
            DigitsOnlyRegex(phone);
        }
        sw2.Stop();
        Console.WriteLine("Time: " + sw2.ElapsedMilliseconds);

        Console.ReadLine();
    }

    public static string DigitsOnly(string phone, string replace = null)
    {
        if (replace == null) replace = "";
        if (phone == null) return null;
        var result = new StringBuilder(phone.Length);
        foreach (char c in phone)
            if (c >= '0' && c <= '9')
                result.Append(c);
            else
            {
                result.Append(replace);
            }
        return result.ToString();
    }

    public static string DigitsOnlyRegex(string phone)
    {
        return digitsOnly.Replace(phone, "");
    }
}

내 컴퓨터의 결과는 다음과 같습니다 :
초기화 ...
시간 : 307
시간 : 2178


벤치 마크 표시에 +1 StringBuilder가있는 루프가 RegEx를 능가한다는 점에 흥미가 있지만 RegEx가 무엇을 해야할지 결정하기 위해 많은 규칙을 통과해야 할 때 의미가 있다고 생각합니다.
Steve In CO

3

더 효율적인 방법이 있다고 확신하지만 아마도 이렇게 할 것입니다.

string getTenDigitNumber(string input)
{    
    StringBuilder sb = new StringBuilder();
    for(int i - 0; i < input.Length; i++)
    {
        int junk;
        if(int.TryParse(input[i], ref junk))
            sb.Append(input[i]);
    }
    return sb.ToString();
}

그것이 나의 첫 본능이었고, 또한 내가 여기서 물었던 이유이기도합니다. RegEx는 나에게 훨씬 더 나은 솔루션처럼 보입니다. 그러나 답변 주셔서 감사합니다!
매트 도디

-1

이 시도

public static string cleanPhone(string inVal)
        {
            char[] newPhon = new char[inVal.Length];
            int i = 0;
            foreach (char c in inVal)
                if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0)
                    newPhon[i++] = c;
            return newPhon.ToString();
        }

return newPhone.ToString();"System.Char []"를 반환합니다. 나는 당신이 의미 생각 return new string(newPhone);하지만이 또한 숫자 0 때문에 9 필터링됩니다 ><대신 >=하고 <=. 그러나 newPhon배열이 필요한 것보다 길기 때문에 문자열에도 후행 공백이 생깁니다 .
juharr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.