2013-02-05 2 views
1

좋아, 나는 명백하게 그러나 명백하게 사소한 문제를 해결해야한다.독점적으로 교체하는 방법은 무엇입니까?

간단한 문자열 ab이 있다고 가정합니다.
이제 abb으로 바꾸고 a으로 바꾸겠습니다. 따라서 ba으로 끝납니다.

해결 방법은 두 가지를 연속적으로 대체하는 것입니다. 하지만 그 결과는 주문에 따라 aa 또는 bb입니다.

분명히 생산 상황은 두 가지보다 훨씬 복잡한 문자열과 대체물을 처리해야하지만 문제는 여전히 적용됩니다.

제가 가지고 있었던 한 가지 아이디어는 내가 대체 한 위치를 저장하는 것이 었습니다. 그러나 대체품이 원래 바늘과 다른 길이로되자 마자 나를 버렸습니다.

이것은 일반적인 문제이지만 C#으로 작업하고 있습니다. 여기에 나와있는 몇 가지 코드가 있습니다.

string original = "abc"; 

Regex[] expressions = new Regex[] 
{ 
    new Regex("a"), //replaced by ab 
    new Regex("b") //replaced by c 
}; 

string[] replacements = new string[] 
{ 
    "ab", 
    "c" 
}; 

for (int i = 0; i < expressions.Length; i++) 
    original = expressions[i].Replace(original, replacements[i]); 

//Expected result: abcc 
//Actual result: accc <- the b is replaced by c in the second pass. 

그래서 이것을 해결할 수있는 간단한 방법이 있습니까?

+0

2 자 이상인 경우 어떻게 바뀌나요? –

+1

몇 가지 코드를 볼 수 있습니까? –

+0

대체 문자가 단 하나의 문자 (대체되는 문자와 대체되는 문자) 인 경우, 이는 단일 패스 알고리즘입니다. 각 입력 문자에 대해 대체가 필요하면 대체해야하며 그렇지 않으면 캐릭터. 당신이 단지 두자를 대체하지 않는 한 아마 참조하기 쉬운 교체 테이블을 만드는 것이 가장 쉽다. – twalberg

답변

1

당신이 char 배열로 변환 스위치를하고, 간단한 일대일 변환에 대해 이야기하는 경우는, 그러나 당신이 찾고있는 사람이 될 아마 이상적인 것입니다 더 복잡한 대체.

기본적으로 속임수는 임시 문자를 표시하는 중간 문자를 만드는 것입니다.오히려 실제 코드를 보여주는 것보다, 여기에 문자열이 변형되면서 같을 것이다 것입니다 :

ab 
%1b 
%1%2 
b%2 
ba 

그래서 기본적으로, 등등 %1와 함께, %%로 후 첫 경기를 %를 교체합니다. 모두 완료되면 %1을 출력으로 바꾸고 마지막으로 %%%으로 대체하십시오.

중간 구문이 당신이 입력 한 내용을 손상시키지 않는다고 보장 할 수 있다면, 그렇지 않으면, 당신이 기수로 시작하지 않도록 트릭을 사용해야 할 것입니다. %. (따라서 %%a은 일치하지만 은 특별한 값 %a을 의미하므로

0

(\ba\b)을 사용하여 문자가 a이고 문자가 a 인 경우 ab은 일치하지 않습니다. b과 유사하게 (\bb\b)이됩니다.

string original = "a b c"; 
Regex[] expressions = new Regex[] { 
     // @ sign used to signify a literal string 
     new Regex(@"(\ba\b)"), // \b represents a word boundary, between a word and a space 
     new Regex(@"(\bb\b)"), 
}; 
string[] replacements = new string[] { 
     "ab", 
     "c" 
}; 
for(int i = 0; i < expressions.Length; i++) 
     original = expressions[i].Replace(original, replacements[i]); 

편집 1 : 일치하는 글자 사이에 공백없이 변경 질문, 난 그냥 정규 표현식이 확인 된 순서를 반전 abc에서 같은 abcc을 원했다.

Regex[] expressions = new Regex[] { 
     new Regex(@"b"), //replaced by c 
     new Regex(@"a"), //replaced by ab 
}; 
string[] replacements = new string[] { 
     "c", 
     "ab", 
}; 

편집 2 : 대답이이 패턴에 대한 검사를 확인하는 패턴의 순서에 따라 일치 일치하도록 가변 길이를 반영하도록 변경 한 후

string original = "a bc"; 

Regex[] expressions = new Regex[] { 
     new Regex(@"a"), //replaced by ab 
     new Regex(@"b"), //replaced by c 
}; 

string[] replacements = new string[] { 
     "ab", 
     "c", 
}; 
string newString = string.Empty; 
string workingString = string.Empty; 
// Position of start point in string 
int index = 0; 
// Length to retrieve 
int length = 1; 
while(index < original.Length) { 
     // Retrieve a piece of the string 
     workingString = original.Substring(index, length); 
     // Whether the expression has been matched 
     bool found = false; 
     for(int i = 0; i < expressions.Length && !found; i++) { 
      if(expressions[i].Match(workingString).Success) { 
       // If expression matched, add the replacement value to the new string 
       newString += expressions[i].Replace(workingString, replacements[i]); 
       // Mark expression as found 
       found = true; 
      } 
     } 
     if(!found) { 
      // If not found, increase length (check for more than one character patterns) 
      length++; 
      // If the rest of the entire string doesn't match anything, move the character at **index** into the new string 
      if(length >= (original.Length - index)) { 
       newString += original.Substring(index, 1); 
       index++; 
       length = 1; 
      } 
     } 
     // If a match was found, start over at next position in string 
     else { 
      index += length; 
      length = 1; 
     } 
} 
+0

문자열의 바늘 사이에 반드시 공백이 없어야합니다 ... –

+0

@Cobra_Fast 동일한 결과를 원한다면 먼저 확인한 내용을 되돌리고 'b'를 확인한 다음 모두 b를 대체하십시오 '를'c'로 바꾸고,'a'를 검사하고'ab'로 바꾸면,'ab'에서'b'가 대체되지 않습니다. –

+0

당신은 내 대답에있는 * 예 *에 너무 가깝게 머물러 있습니다. 주문, 문자열 및 교체는 많이 다를 수 있습니다. –

1

여기 하나 개의 솔루션의 새로운 문자열로 이동 . 문자열에 대해 모든 정규 표현식을 시도하고, 가장 빠른 시합에서 교체를 수행 한 다음 문자열의 나머지 부분을 반복합니다. 이 작업이 더 빠르지 만 복잡해지면 시작 부분에 모두 Matches()을 입력하고 왼쪽에서 오른쪽으로 처리하고 더 긴 문자열과 짧은 문자열로 표현식을 바꿀 때 Indexes을 조정하고 겹치기를 버릴 수 있습니다.

using System; 
using System.IO; 
using System.Text.RegularExpressions; 

class MultiRegex { 

    static String Replace(String text, Regex[] expressions, 
      String[] replacements, int start=0) 
    { 
     // Try matching each regex; save the first match 
     Match firstMatch = null; 
     int firstMatchingExpressionIndex = -1; 
     for (int i = 0; i < expressions.Length; i++) { 
      Regex r = expressions[i]; 
      Match m = r.Match(text, start); 
      if (m.Success 
        && (firstMatch == null || m.Index < firstMatch.Index)) 
      { 
       firstMatch = m; 
       firstMatchingExpressionIndex = i; 
      } 
     } 

     if (firstMatch == null) { 
      /* No matches anywhere */ 
      return text; 
     } 

     // Replace text, then recurse 
     String newText = text.Substring(0, firstMatch.Index) 
      + replacements[firstMatchingExpressionIndex] 
      + text.Substring(firstMatch.Index + firstMatch.Length); 
     return Replace(newText, expressions, replacements, 
       start + replacements[firstMatchingExpressionIndex].Length); 
    } 

    public static void Main() { 

     Regex[] expressions = new Regex[] 
     { 
      new Regex("a"), //replaced by ab 
      new Regex("b") //replaced by c 
     }; 

     string[] replacements = new string[] 
     { 
      "ab", 
      "c" 
     }; 

     string original = "a b c"; 
     Console.WriteLine(
       Replace(original, expressions, replacements)); 

     // Should be "baz foo bar" 
     Console.WriteLine(Replace("foo bar baz", 
        new Regex[] { new Regex("bar"), new Regex("baz"), 
         new Regex("foo") }, 
        new String[] { "foo", "bar", "baz" })); 
    } 
} 

이 지문 :

ab c c 
baz foo bar 
관련 문제