2009-09-03 42 views
14

如果我執行以下語句:爲什麼string.Compare似乎不一致地處理重音字符?

string.Compare("mun", "mün", true, CultureInfo.InvariantCulture) 

結果是「-1」,表明「門」與「門」的數值更低。

但是,如果我執行該語句:

string.Compare("Muntelier, Schweiz", "München, Deutschland", true, CultureInfo.InvariantCulture) 

我得到 '1',表明 '曼泰利耶,Schewiz' 應該走過去。

這是比較中的錯誤嗎?或者更可能的,是有一個規則,我應該字符串進行排序,當包含重音


的原因,這是一個問題,是因爲考慮到,我在整理列表,然後這樣做的意思手動二進制過濾器獲取以'xxx'開頭的每個字符串。

此前我使用的是Linq'Where'方法,但是現在我必須使用由另一個人編寫的這個自定義函數,因爲他說它表現更好。

但是自定義函數似乎沒有考慮到.NET所具有的任何'unicode'規則。因此,如果我告訴它按'mün'進行過濾,即使列表中有以'mun'開頭的項目,它也不會找到任何項目。

這似乎是因爲重音字符的排序不一致,這取決於重音字符之後的字符。


OK,我想我已經解決了這一問題。

過濾器之前,我做基於每個字符串,其中ñ是搜索字符串的長度的第一ñ字母排序。

+0

它的時刻是這樣,我希望在.NET Framework是開放源代碼的,所以我可以在調試模式下逐步完成並找出它正在做什麼。 – Jonathan

+4

@jonathanconway:單步執行基類庫的源代碼是可能的,請參閱http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net- framework-source-code.aspx –

+0

@divo感謝您的參考。從未意識到這是可能的! – Jonathan

回答

22

有在工作中平局決勝算法,見http://unicode.org/reports/tr10/

爲了解決 語言敏感排序的複雜性,一個 多層次比較算法是採用 。在比較兩個詞裏, 例如,最重要的特徵是 基字符:如A和B. 口音差之間的差 通常 忽略,如果有在基座字母的任何差異 。情況下的差異 (大寫與小寫),是 通常被忽略,如果有在基或修飾任何 差異。 標點符號是可變的。在某些 情況下,標點符號是 ,就像基本字符一樣對待。在 等情況下,應該忽略 如果有任何基數,重音或者情況 的差異。還可能有一個最終的平局決勝等級,如果 在字符串中全部沒有其他差異 ,則使用(標準化)代碼 點順序。

因此,「Munt ...」和「Münc...」按字母順序不同,並根據「t」和「c」排序。

然而,「門」和「門」是按字母順序相同(「U」 equivelent在失去了語言的「U」)這樣的字符編碼對比

6

它看起來像重音字符只用於某種「tie-break」的情況 - 換句話說,如果字符串是平等的。

下面是一些示例代碼來演示:(我試過後的「N」,以及加空格,看它是否是在字邊界做 - 它不是)

using System; 
using System.Globalization; 

class Test 
{ 
    static void Main() 
    { 
     Compare("mun", "mün"); 
     Compare("muna", "münb"); 
     Compare("munb", "müna"); 
    } 

    static void Compare(string x, string y) 
    { 
     int result = string.Compare(x, y, true, 
            CultureInfo.InvariantCulture)); 

     Console.WriteLine("{0}; {1}; {2}", x, y, result); 
    } 
} 

結果:

mun; mün; -1 
muna; münb; -1 
munb; müna; 1 

我懷疑這是由各種複雜的Unicode規則正確的 - 但我不知道有足夠的瞭解他們。

至於你是否需要考慮這一點...我不會這麼期待的。你在做什麼,這是由此引發的?

4

據我瞭解,這仍然有點一致。使用CultureInfo.InvariantCulture進行比較時,變音符號ü被視爲非重音字符u

作爲你的第一個例子中的字符串顯然是不相等的結果不會是0,但是-1(這似乎是默認值)。在第二個例子曼泰利耶進入最後因爲如下Ç字母表。

我無法找到任何MSDN文檔清晰解釋這些規則,但我發現,

string.Compare("mun", "mün", CultureInfo.InvariantCulture, 
    CompareOptions.StringSort); 

string.Compare("Muntelier, Schweiz", "München, Deutschland", 
    CultureInfo.InvariantCulture, CompareOptions.StringSort); 

給出了期望的結果。

無論如何,我認爲你會是好到你的基礎上的特定文化排序,如當前用戶的文化(如果可能)。

+0

'CompareOptions.Ordinal'也可以是一個選項。使用此選項,字符串將根據Unicode值進行比較。請參閱http://msdn.microsoft.com/en-us/library/system.globalization.compareoptions.aspx。 –

相關問題