문제

내가 지정한 문자를 제외한 모든 문자를 대체하는 방법이 있습니다. 예를 들어,

ReplaceNot("test. stop; or, not", ".;/\\".ToCharArray(), '*'); 

돌아올 것입니다

"****.*****;***,****".

이제 이것은 조기 최적화의 사례가 아닙니다. 네트워크 작업 중에이 방법을 상당히 몇 번 호출합니다. 더 긴 줄에서는 약간의 대기 시간이 발생하고 제거하는 것이 약간 도움이된다는 것을 알았습니다. 이 속도를 높이는 데 도움이 될 것입니다.

    public static string ReplaceNot(this string original, char[] pattern, char replacement)
    {           
        int index = 0;
        int old = -1;

        StringBuilder sb = new StringBuilder(original.Length);

        while ((index = original.IndexOfAny(pattern, index)) > -1)
        {
            sb.Append(new string(replacement, index - old - 1));
            sb.Append(original[index]);
            old = index++;
        }

        if (original.Length - old > 1)
        {
            sb.Append(new string(replacement, original.Length - (old + 1)));
        }

        return sb.ToString();
    }

최종 #의. 또한 3K 문자열에 대한 테스트 케이스를 추가했으며 1m 대신 100k 회로 실행하여 각 스케일이 얼마나 잘 있는지 확인했습니다. 유일한 놀라움은 정규 표현이 다른 표현보다 '스케일링'되었다는 것이었지만, 시작하는 것은 매우 느리기 때문에 도움이되지 않습니다.

User            Short * 1M  Long * 100K     Scale
John            319             2125            6.66
Luke            360             2659            7.39
Guffa           409             2827            6.91
Mine            447             3372            7.54
DirkGently      1094            9134            8.35
Michael         1591            12785           8.04
Peter           21106           94386           4.47

업데이트 : Peter 버전의 정규 표현식을 정적 변수로 만들었고 RegexOptions.com으로 설정했습니다.

User            Short * 1M      Long * 100K     Scale
Peter           8997            74715           8.30

테스트 코드에 대한 붙여 넣기 링크, 잘못된 경우 수정하십시오. http://pastebin.com/f64f260ee

도움이 되었습니까?

해결책

좋아, ~ 60kb 문자열에서, 이것은 버전보다 약 40% 더 빠르게 수행됩니다.

public static string ReplaceNot(this string original, char[] pattern, char replacement)
{
    int index = 0;

    StringBuilder sb = new StringBuilder(new string(replacement, original.Length));

    while ((index = original.IndexOfAny(pattern, index)) > -1)
    {
        sb[index] = original[index++];
    }

    return sb.ToString();
}

요령은 대부분의 교체 문자로 새 문자열을 초기화하는 것입니다.

다른 팁

regex.replace를 사용할 수 없습니다.

Regex regex = new Regex(@"[^.;/\\]");
string s = regex.Replace("test. stop; or, not", "*");

이것이 더 빨라질 지 모르겠지만 문자열 빌더에 추가 될 수 있도록 끈을 새롭게하지 않아서 도움이 될 수 있습니다.

    public static string ReplaceNot(this string original, char[] pattern, char replacement)
    {
        StringBuilder sb = new StringBuilder(original.Length);

        foreach (char ch in original) {
            if (Array.IndexOf( pattern, ch) >= 0) {
                sb.Append( ch);
            }
            else {
                sb.Append( replacement);
            }
        }

        return sb.ToString();
    }

숯의 수에있는 경우 pattern 어떤 크기 가든 (일반적으로 그렇지 않을 것 같아요), 그것은 분류하고 수행하기 위해 비용을 지불 할 수 있습니다. Array.BinarySearch() 대신 Array.indexOf().

그런 간단한 변형의 경우, 나는 그것이 정규식보다 더 빠른 문제가 없을 것이라고 확신합니다.

또한 캐릭터 세트 이후 pattern 어쨌든 일반적으로 문자열에서 나올 가능성이 높습니다 (적어도 그것은이 유형의 API에 대한 나의 일반적인 경험이었습니다).

public static string ReplaceNot(this string original, string pattern, char replacement)

또는 더 나은 아직, 과부하가있는 곳이 있습니다 pattern a char[] 또는 string?

다음은 다른 버전입니다. 내 테스트는 그 성능이 꽤 좋다고 제안합니다.

public static string ReplaceNot(
    this string original, char[] pattern, char replacement)
{
    char[] buffer = new char[original.Length];

    for (int i = 0; i < buffer.Length; i++)
    {
        bool replace = true;

        for (int j = 0; j < pattern.Length; j++)
        {
            if (original[i] == pattern[j])
            {
                replace = false;
                break;
            }
        }

        buffer[i] = replace ? replacement : original[i];
    }

    return new string(buffer);
}

StringBuilder에는 문자와 카운트를 취하는 오버로드가 있으므로 StringBuilder에 추가하기 위해 중간 문자열을 만들 필요가 없습니다. 이것을 대체하여 약 20%의 개선을받습니다.

sb.Append(new string(replacement, index - old - 1));

와 함께:

sb.Append(replacement, index - old - 1);

이:

sb.Append(new string(replacement, original.Length - (old + 1)));

와 함께:

sb.Append(replacement, original.Length - (old + 1));

(나는 당신이 말한 코드를 4 배 더 빠르게 테스트했는데 약 15 배 더 느린 느낌이 듭니다 ...)

O (n)가 될 것입니다. 당신은 모든 알파벳과 공백을 대체하는 것 같습니다. *, 현재 캐릭터가 알파벳/공백인지 테스트하고 교체하지 않겠습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top