2009-09-08 99 views
36

我想知道什麼是正確的方式來比較兩個字符忽略案件,將適用於所有文化。另外,Comparer<char>.Default是測試兩個字符而不忽略大小寫的最佳方法嗎?這是否適用於代理對?比較char忽略大小寫的正確方法是什麼?

編輯:新增樣本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 2013-11-20 14:44:01

回答

63

這取決於你的意思是「工作人工作升文化「。你想讓「我」和「我」在土耳其平等嗎?

你可以使用:

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

...但我不知道是否該「工程」根據你的「作品」的瞭解所有文化。

當然,你可以將兩個字符轉換爲字符串,然後在字符串上執行任何你想要的比較。有點低效率的,但它確實給你的框架可比較的所有範圍:

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

代孕對,Comparer<char>不會是可行的,無論如何,因爲你沒有一個單一的char做。不過你可以創建一個Comparer<int>

+0

這就是我曾經想過在你的兩個例子中都這樣做的方式,但是認爲可能有更好的方式,我不知道這個框架提供了什麼。我在LINQ擴展方法的上下文中考慮了String.Contains(char,IEqualityComparer ) – 2009-09-08 16:27:58

+1

沒有框架方法:字符串比較實際上是使用本地方法實現的,而不是通過下降到比較器實現。 – 2009-09-09 08:48:19

+0

@TimSchmelter:不,由於某種原因設法錯過了。最後添加了一個快速註釋。 – 2015-05-07 07:44:08

1

string.Compare( 「字符串」, 「字符串中的」真)

它將爲每個字符串

+1

您好Sergio,我後來比較兩個字符實例,而不是字符串實例。我正在尋找一個忽略大小寫的Comparer 實現。 – 2009-09-08 16:19:56

+8

這在英語國家非常適用。但是,東歐沒有人會使用您編寫的應用程序。 – 2009-09-08 16:22:18

+2

@Jon Grant:我在我的國家(葡萄牙)使用這種語言,葡萄牙語是一種拉丁語言,它有許多「奇怪」的字符,如:ãéàç,它對我來說非常合適。 – Sergio 2009-09-08 16:33:38

12

使用默認值(即不變)文化:

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

或指定文化:

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

我不能投票,但我確實給了你一票,因爲我認爲你的解決方案是相當適當的答案。 – 2009-09-08 17:36:19

+0

這不是問題的答案。 – 2009-09-08 18:39:24

+0

喬恩同意了,但我讀到「這將適用於所有文化」,有點過分樂觀和不切實際。我應該說明顯的。 – 2009-09-08 21:13:49

2

據我所知,沒有真正的方式,將「爲所有文化而工作」。要麼爲某種內部的,非顯示的用戶原因比較字符(在這種情況下,您應該使用InvariantCulture),或者要使用用戶的CurrentCulture。顯然,使用用戶當前的文化將意味着您將在不同的語言環境中獲得不同的結果,但它們將與這些語言環境中的用戶期望的結果一致。

不知道爲什麼你比較兩個字符,我不能真正告訴你應該使用哪一個。

+0

感謝Jon,這是一個普遍的問題,我對unicode不熟練,並且認爲我會在這裏提出問題。考慮一下LINQ提供的String.Contains(char,IEqualityComparer )擴展方法,那麼實現它的正確方法是區分大小寫? – 2009-09-08 16:25:47

+0

再一次,這將取決於數據是什麼以及爲什麼要進行比較。例如,你只是想把事情分成一些一致的順序,使用任何不同的比較都可以。如果您對用戶輸入做出了響應,那麼您可能希望使用該用戶的文化來爲他們提供他們期望的結果。我不確定是否真的有「一刀切」的答案。 – 2009-09-08 16:30:55

+0

您是否認爲我的Comparer實現作爲答案提供是一種正確的方法? – 2009-09-08 16:51:37

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));'而不是。 – 2009-11-13 16:14:25

+0

@MattHowells我會爭辯說...請參閱'char.CompareTo(char)':'return(m_value-value);' – 2014-05-27 08:27:43

0

我會建議比較大寫的,如果他們不匹配,那麼比較小寫,以防萬一語言環境的uppercasing而低級邏輯表現稍有不同。

補遺

例如,

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