2011-05-30 63 views
6

我需要做這樣的事情的夢想​​:替換無效字符的列表,其有效版本(如TR)

str = str.trReplace("áéíüñ","aeiu&"); 

應該改變這個字符串:

a stríng with inválid charactérs 

到:

a string with invalid characters 

我目前的想法是:

str = str.Replace("á","a").Replace("é","e").Replace("í","ï"... 

和:

sb = new StringBuilder(str) 
sb.Replace("á","a"). 
sb.Replace("é","e") 
sb.Replace("í","ï"... 

但我不認爲他們是有效率的長字符串。

回答

4

Richard有一個很好的答案,但性能可能會受到較長的字符串的影響(比直接字符串替換慢25%左右,如問題所示)。我覺得自己完全可以看得更深一點。實際上,有幾個很好的相關答案已經在計算器上,如下捕獲:

Fastest way to remove chars from string

C# Stripping/converting one or more characters

還有在CodeProject上的好文章涵蓋了不同的選擇。

http://www.codeproject.com/KB/string/fastestcscaseinsstringrep.aspx

要解釋爲什麼在理查茲的答案提供的功能變慢更長的字符串是由於一個事實,即替換正在發生一次一個字符;因此如果你有大量的非映射字符序列,那麼你會浪費額外的週期,同時重新添加字符串。因此,如果你想從CodePlex上。本文以幾個點你最終理查茲回答略加修改的版本,看起來像:

private static readonly Char[] ReplacementChars = new[] { 'á', 'é', 'í', 'ü', 'ñ' }; 
private static readonly Dictionary<Char, Char> ReplacementMappings = new Dictionary<Char, Char> 
                   { 
                   { 'á', 'a'}, 
                   { 'é', 'e'}, 
                   { 'í', 'i'}, 
                   { 'ü', 'u'}, 
                   { 'ñ', '&'} 
                   }; 

private static string Translate(String source) 
{ 
    var startIndex = 0; 
    var currentIndex = 0; 
    var result = new StringBuilder(source.Length); 

    while ((currentIndex = source.IndexOfAny(ReplacementChars, startIndex)) != -1) 
    { 
    result.Append(source.Substring(startIndex, currentIndex - startIndex)); 
    result.Append(ReplacementMappings[source[currentIndex]]); 

    startIndex = currentIndex + 1; 
    } 

    if (startIndex == 0) 
    return source; 

    result.Append(source.Substring(startIndex)); 

    return result.ToString(); 
} 

注意並非所有的邊緣情況進行了測試。

備註可能會用ReplacementMappings.Keys.ToArray()代替ReplacementChars,但花費很少。

假設不是每個字符都是替換字符,那麼這實際上比straigt字符串替換(再次約20%)的運行速度稍快。這就是說,記住當考慮性能成本時,我們實際上在談論...在這種情況下......優化解決方案和原始解決方案之間的差異是在1000個字符串中超過100,000次迭代大約1秒鐘。

無論哪種方式,只是想添加一些信息到這個問題的答案。

1

你想要的是通過一次字符串並完成所有替換的方法。如果你想提高效率,我不確定這個正則表達式是否是最好的方法。在for循環中測試每個字符的情況切換(對於所有想要替換的字符)可能會更快。我會介紹這兩種方法。

2

我爲ICAO護照做了類似的事情。名字必須是'音譯'。基本上我有一個字符char到char映射。

Dictionary<char, char> mappings; 

static public string Translate(string s) 
{ 
    var t = new StringBuilder(s.Length); 
    foreach (char c in s) 
    { 
     char to; 
     if (mappings.TryGetValue(c, out to)) 
     t.Append(to); 
     else 
     t.Append(c); 
    } 
    return t.ToString(); 
} 
+0

謝謝,它對我來說看起來很有效率。我將開始編碼(我會在你有足夠的聲望後立即投票給你):-) – MiguelM 2011-05-30 01:15:17

+0

@ Richard - 做了一個小錯誤修正。由於我的代碼設置是基於您的方法和問題的方法進行基準測試,因此實際上它與短字符串替換時的運行時間相同,並且實際上在較長的字符串上運行速度較慢?思考? – 2011-05-30 01:24:13

相關問題