2009-09-08 18 views
36

私は2つの文字を比較する正しい方法がすべての文化のために働く大文字小文字を無視しているのだろうかと思っています。また、大文字小文字を無視しないで2文字をテストする最良の方法はComparer<char>.Defaultですか?これはサロゲートペアでも機能しますか?大文字小文字を無視して大文字小文字を比較する正しい方法は何ですか?

EDIT:追加サンプルIComparer<char>実装

これは誰を助けている場合、これは私が

public class CaseInsensitiveCharComparer : IComparer<char> { 
    private readonly System.Globalization.CultureInfo ci; 
    public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) { 
     this.ci = ci; 
    } 
    public CaseInsensitiveCharComparer() 
     : this(System.Globalization.CultureInfo.CurrentCulture) { } 
    public int Compare(char x, char y) { 
     return Char.ToUpper(x, ci) - Char.ToUpper(y, ci); 
    } 
} 

// Prints 3 
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer())); 
+0

TOUPPERは、現在の文化に対する正しい大文字に文字を変換することができるが、返された字句順序が正しくありません。おそらく、これは文字列比較のために.NETでのみサポートされています。 – Holstebroe

答えて

63

のために働くだろう真)

lカルチャー "。トルコでも "私"と "私"が同じであることを望みますか?

あなたが使用することができ

bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y); 

...しかし、私はそれが「作品」のご理解により、すべての文化に応じて「作品」かどうかはわかりません。

もちろん、両方の文字を文字列に変換してから、文字列の任意の比較を実行できます。とにかく実現可能であることを行っていないあなたは、単一のcharを持っていないので、サロゲートペアのために

bool equal = x.ToString().Equals(y.ToString(), 
           StringComparison.InvariantCultureIgnoreCase); 

Comparer<char>:やや少ない効率的な、それはあなたのフレームワークで利用可能なすべての比較範囲を与えるん。あなたはComparer<int>を作成することができます。私はそれを理解し、その方法は本当にありません

CultureInfo myCulture = ...; 
if (char.ToLower(ch1, myCulture) == char.ToLower(ch2, myCulture)) 
{ .... } 
+0

それは私があなたの両方の例でそれをやっていると思った方法ですが、フレームワークが提供することがわかっていないより良い方法があるかもしれないと思った。 String.Contains(char、IEqualityComparer ) –

+1

のLINQ拡張メソッドのコンテキストで考えていました。このためのフレームワークメソッドはありません:文字列の比較は、ネイティブメソッドを使用して実装されていますが、Comparer の実装にはドロップされません。 –

+0

@TimSchmelter:いいえ、何らかの理由でそれを見逃してしまいました。最後に簡単なメモを追加しました。 –

1

string.Compare( "列A"、 "STRINGのA" を使用することを決定したもので、それはあなたがアルのための仕事」によって何を意味するかに依存してすべての文字列

+1

こんにちはSergio、私は文字インスタンスではなく、2つのcharインスタンスを比較する方法の後です。私は、大文字小文字を無視するComparer の実装を探しています。 –

+8

これは英語圏の国ではうまくいきます。しかし、東ヨーロッパの誰もあなたが書いたアプリケーションを使用することはありません。 –

+2

@ジョングラント:私は私の国(ポルトガル)でこれを使用しています。ポルトガル語はラテン語ベースの言語で、「奇妙な」文字のようなものがたくさんあります。 – Sergio

12

「すべての文化のために働く」。いずれかの種類の内部、非表示のユーザー理由(この場合はInvariantCultureを使用する必要があります)、またはユーザーのCurrentCultureを使用したい場合は、文字を比較します。明らかに、ユーザーの現在のカルチャーを使用することは、異なるロケールで異なる結果を得ることを意味しますが、それらのロケールのユーザーが期待するものと一貫しています。

なぜ2文字を比較しているのか分かりませんが、どの文字を使用するべきかあなたに本当にアドバイスできません。

+0

私は落ちることはできませんが、私はあなたの解決策がかなり適切に答えられていると思っていますので、私はあなたに投票をしました。 –

+0

これは質問に対する答えではありません。 –

+0

ジョンは同意しましたが、私は少し楽観的で非現実的なものとして「すべての文化のために働くでしょう」と読んでいます。私は明白なことを述べておくべきだった。 –

2

if (char.ToLower(ch1) == char.ToLower(ch2)) 
{ .... } 

または培養物を指定します(つまり、ない不変である)文化のデフォルトを使用して

+0

ありがとうございましたジョン、それは一般的な質問です、私はユニコードに精通していないと私はここで質問をするだろうと思った。 LINQが提供するString.Contains(char、IEqualityComparer )拡張メソッドを考えてください。大文字と小文字を区別しないで実装する正しい方法は何でしょうか? –

+0

また、実際にはデータの内容とそれを比較した理由に依存します。たとえば、さまざまな不変式の比較を使用して、ある種の一貫した順序でソートするだけでよいでしょう。ユーザー入力に応答している場合は、おそらくそのユーザーのカルチャーを使用して、期待した結果を与えることが必要です。私は実際には "1つのサイズがすべての答え"に該当するかどうかはわかりません。 –

+0

答えとして提供された私のComparerの実装が正しいアプローチだろうと思いますか? –

0

あなたは試みることができる:

class Test{ 
    static int Compare(char t, char p){ 
     return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase); 
    } 
} 

をしかし、私は、これはそれを行うには、「最適な」方法です疑うが、私は、あなたがチェックする必要がある例すべてではありませんよ...

0

私はそれがランタイム内で利用できるようになる考えていたが、私は大文字を比較する推薦する、と彼らは小文字を比較し、その後一致しない場合は、ちょうどロケールの大文字化する場合に、次の

public class CaseInsensitiveCharComparer : IComparer<char> { 
    private readonly System.Globalization.CultureInfo ci; 
    public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) { 
     this.ci = ci; 
    } 
    public CaseInsensitiveCharComparer() 
     : this(System.Globalization.CultureInfo.CurrentCulture) { } 
    public int Compare(char x, char y) { 
     return Char.ToUpper(x, ci) - Char.ToUpper(y, ci); 
    } 
} 

// Prints 3 
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer())); 
+1

将来のCLRバージョンでは、引き算による文字の比較が正しいと仮定するのは危険です。代わりに 'return Char.ToUpper(x、ci).CompareTo(Char.ToUpper(y、ci));'を使用します。 –

+0

@MattHowells私はそれを議論するつもりです... 'char.CompareTo(char)'を参照してください: 'return(m_value-value);' –

0

のようなものです小文字のロジックはわずかに異なる動作をします。例えば

補遺

int CompareChar(char c1, char c2) 
{ 
    int dif; 

    dif = char.ToUpper(c1) - char.ToUpper(c2); 
    if (diff != 0) 
     dif = char.ToLower(c1) - char.ToLower(c2); 
    return dif; 
} 
関連する問題