2009-09-08 190 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; 
}