2009-09-03 10 views
14

は、私は次の文を実行した場合:string.Compareがアクセント付きの文字を一貫して扱えないのはなぜですか?

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

結果は「-1」、「三菱UFJニコスは、」「ムン」より低い数値を持っていることを示しています。しかし

、私はこの文を実行した場合:

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

私は 'ムンテリアー、Schewizは' 最後に行くべきであることを示し、 '1' を取得します。

これは比較のバグですか?または、より多くの可能性が、これは、私はリストを、問題をソートしていますし、その後、意味の取扱説明書バイナリフィルタをやっている理由は、アクセント


を含む文字列をソートするとき、私は考慮に入れてしなければならないルールがあります'xxx'で始まるすべての文字列を取得します。

私はLinq 'Where'メソッドを使用していましたが、今は他の人が作成したこのカスタム関数を使用する必要があります。

しかし、カスタム関数は、.NETが持つ「ユニコード」のルールを考慮していないようです。だから私が 'mun'でフィルタするように言うなら、 'mun'で始まるリストに項目があっても、それは何の項目も見つけられません。

これは、アクセント付きの文字の後にどの文字が来るかによって、アクセント付きの文字の順序が矛盾しているためです。


問題は解決したと思います。

はフィルタの前に、私はのnは、検索文字列の長さである各文字列の最初のn 手紙に基づいて並べ替えを行います。

+0

を比較していることは、私は、.NET Frameworkを望むこのような瞬間ですオープンソースだったので、私はデバッグモードでステップを踏んで、何をしているのかを正確に把握することができました。 – Jonathan

+4

@jonathanconway:基本クラスライブラリのソースコードを実行することは可能です。http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-japan/ framework-source-code.aspx –

+0

@divo参考になりました。これが可能であることは決して実現しなかった! – Jonathan

答えて

22

仕事でタイブレークアルゴリズムがあり、 言語に敏感なソートの複雑さに対処するためにhttp://unicode.org/reports/tr10/

を参照してください、 マルチレベルの比較アルゴリズムを採用 です。二つの単語を比較すると、 例えば、最も重要な特徴は 基本文字である:そのようなAとB アクセント差の 差としてベース文字の違い がある場合は、一般的に無視さ です。ベースまたはアクセントに の違いがある場合、大文字と小文字の違い (大文字と小文字)は、通常は無視されます( )。 句読点は可変です。一部の では、句読点文字が のように扱われます。 他の状況では、ベース、アクセント、またはケースがある場合は、 は無視する必要があります。 の違い。また、 の最終的なタイブレークレベルがある場合もあります。 文字列の には他に違いがない場合、(正規化された)コード が使用されます。

"Munt ..."と "Münc..."はアルファベット順に異なり、 "t"と "c"に基づいてソートされます。

「三菱UFJニコス」、一方及び「三菱UFJニコスは、」アルファベット順(失われた言語で「ü」を「U」equivelent)と同じですので、文字コードが

6

アクセント付きの文字は、「タイブレーク」のような状況でのみ使用されているようです。言い換えれば、文字列がそれ以外の場合は同じです。

は、ここに証明するためにいくつかのサンプルコードです:

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); 
    } 
} 

(私はそれがワード境界に行われたかどうかを確認するために、同様の「n」の後にスペースを追加しようとした - そうではありません。)

結果:

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

私は、これは、様々な複雑なUnicodeのルールにより、正確である疑いがある - しかし、私はそれらについて十分に知りません。

これを考慮する必要があるかどうかについては、私はそうは思わないでしょう。これで投げられていることは何ですか?

4

私はこれをまだ理解していますが、まだまだ一貫しています。 CultureInfo.InvariantCultureを使用して比較すると、ウムラウト文字üは非アクセント文字uのように扱われます。

最初の例の文字列が明らかに等しくないため、結果は0ではなく-1(デフォルト値のようです)です。第2の例ではMuntelierが最後になります。tは、アルファベットのcです。

私はこれらのルールを説明する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を参照してください。 –

関連する問題