比较 char 忽略大小写的正确方法是啥?
Posted
技术标签:
【中文标题】比较 char 忽略大小写的正确方法是啥?【英文标题】:What is the correct way to compare char ignoring case?比较 char 忽略大小写的正确方法是什么? 【发布时间】:2022-01-22 06:50:49 【问题描述】:我想知道比较两个忽略大小写的字符的正确方法适用于所有文化。另外,Comparer<char>.Default
是在不忽略大小写的情况下测试两个字符的最佳方法吗?这对代理对有效吗?
编辑:添加示例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()));
【问题讨论】:
ToUpper 可能会将 char 转换为相对于当前区域性的正确大写,但返回的词法顺序不正确。可能这仅在 .NET 中支持用于字符串比较。 【参考方案1】:这取决于您所说的“为所有文化工作”是什么意思。即使在土耳其,您是否希望“i”和“I”相等?
你可以使用:
bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y);
...但是根据您对“有效”的理解,我不确定根据所有文化是否“有效”。
当然,您可以将两个字符都转换为字符串,然后对字符串执行任何您想要的比较。效率稍低,但它确实为您提供了框架中可用的所有比较范围:
bool equal = x.ToString().Equals(y.ToString(),
StringComparison.InvariantCultureIgnoreCase);
对于代理对,Comparer<char>
无论如何都不可行,因为您没有单个 char
。你可以创建一个Comparer<int>
。
【讨论】:
这就是我在您的两个示例中都考虑过的方式,但认为可能存在框架提供的更好的方式,而我不知道存在这种方式。我在考虑 String.Contains(char, IEqualityComparer据我了解,实际上没有一种方法可以“适用于所有文化”。您想要比较字符是出于某种内部的、非向用户显示的原因(在这种情况下,您应该使用 InvariantCulture),或者您想要使用用户的 CurrentCulture。显然,使用用户当前的文化意味着您将在不同的语言环境中获得不同的结果,但它们将与您在这些语言环境中的用户的期望保持一致。
如果不知道为什么要比较两个字符,我无法真正建议您应该使用哪个字符。
【讨论】:
谢谢乔恩,这是一个普遍的问题,我不熟悉 unicode,我想我会在这里提出这个问题。考虑 LINQ 提供的 String.Contains(char, IEqualityComparer我建议比较大写,如果不匹配则比较小写,以防语言环境的大写和小写逻辑表现稍有不同。
附录
例如,
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;
【讨论】:
【参考方案4】:我认为在运行时中可用的内容类似于以下内容
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()));
【讨论】:
假设在未来的 CLR 版本中通过减法进行的 char 比较将继续正确是很危险的,所以我会改用return Char.ToUpper(x, ci).CompareTo(Char.ToUpper(y, ci));
。
@MattHowells 我认为...请参阅char.CompareTo(char)
:return (m_value-value);
【参考方案5】:
string.Compare("string a","STRING A",true)
它适用于每个字符串
【讨论】:
嗨,塞尔吉奥,我正在寻找一种比较两个字符实例的方法,而不是字符串实例。我正在寻找忽略大小写的 Comparer你可以试试:
class Test
static int Compare(char t, char p)
return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase);
但我怀疑这是执行此操作的“最佳”方式,但我并不是您需要检查的所有情况...
【讨论】:
【参考方案7】:我知道这是一篇旧帖子,但从那以后情况发生了变化。
上面的问题可以通过使用扩展来回答。这将扩展 char.Equals 以允许局部性和不区分大小写。
在扩展类中,添加如下内容:
internal static Boolean Equals(this Char src, Char ch, StringComparison comp)
Return $"src".Equals($"ch", comp);
我目前在工作,所以无法检查,但应该可以。
安迪
【讨论】:
非常糟糕的解决方案。涉及许多内存分配。【参考方案8】:您可以为 caseInsensetive 匹配提供最后一个参数为 true
string.Compare(lowerCase, upperCase, true);
【讨论】:
以上是关于比较 char 忽略大小写的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章