2013-02-05 32 views
1

好吧,我有一個非常明顯的但顯然是非平凡的問題來解決。如何獨家更換?

假設我有一個簡單的字符串ab
現在我想用bb替換aa,所以我最終以ba結束。

解決方案的手將是連續做兩個替換。但根據訂單的不同,結果可能是aabb

顯然,生產情況將不得不處理比兩個更復雜的字符串和更多的替換,但問題仍然適用。

我有一個想法是保存我替換的東西的位置。但是,只要替換件的長度不同於原始針的長度,就會使我退出。

這是一般性問題,但我正在使用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

如果你談論的是簡單的一對一轉換,轉換成字符數組,做一個開關可能是理想的,但是你似乎在尋找更復雜的替代品。

基本上訣竅是創建一箇中間字符來標記你的臨時對象。而不是顯示實際的代碼,這裏是字符串會是什麼樣子,因爲它轉化:

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

因此,基本上,用%1等與%%取代%,那麼第一場比賽。完成後,將%1替換爲其輸出等,最後用%代替%%

要小心,如果你可以保證你的中間語法不會污染你的輸入你沒事,如果你不能,你需要使用一些技巧來確保你不是由奇數%。 (所以%%a會匹配,但%%%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