比较字符忽略大小写的正确方法是什么?

问题描述 投票:0回答:10

我想知道比较两个字符的正确方法(忽略大小写)适用于所有文化。另外,

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()));
c# .net string comparison char
10个回答
103
投票

这取决于“为所有文化工作”的含义。即使在土耳其,您也希望“i”和“I”相等吗?

您可以使用:

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

...但我不确定根据您对“作品”的理解,这是否适合所有文化。

当然,您可以将这两个字符都转换为字符串,然后对字符串执行您想要的任何比较。效率稍低,但它确实为您提供了框架中可用的所有比较范围:

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

对于代理对,

Comparer<char>
无论如何都是不可行的,因为你没有一个
char
。不过,您可以创建一个
Comparer<int>


15
投票

使用默认(即不是不变)文化:

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

或指定文化:

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

4
投票

据我了解,并没有真正的方法“适用于所有文化”。您要么出于某种内部的、不向用户显示的原因想要比较字符(在这种情况下您应该使用 InvariantCulture),要么想要使用用户的 CurrentCulture。显然,使用用户当前的文化意味着您将在不同的区域设置中获得不同的结果,但它们将与这些区域设置中的用户所期望的结果一致。

如果不知道为什么要比较两个角色,我无法真正建议您应该使用哪一个。


1
投票

我建议比较大写,如果它们不匹配,则比较小写,以防区域设置的大写和小写逻辑表现略有不同。

附录

例如,

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

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

0
投票

在 .NET Core 和 .NET 5+ 中,您可以使用

ReadOnlySpan<char>.CompareTo
扩展方法(来自
System.MemoryExtensions
)。

您需要使用

ReadOnlySpan
“破解”
MemoryMarshal.CreateReadOnlySpan

var comparisonType = StringComparison.InvariantCultureIgnoreCase; 

var comparison = MemoryMarshal.CreateReadOnlySpan(ref charA, 1).CompareTo(
    MemoryMarshal.CreateReadOnlySpan(ref charB, 1),
    comparisonType);

-1
投票

你可以尝试:

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

但我怀疑这是“最佳”方法,但我并不是你需要检查的所有情况......


-2
投票

string.Compare("字符串 a","STRING A",true)

它适用于每个字符串


-3
投票

我知道这是一篇旧帖子,但从那时起事情已经发生了变化。

上面的问题可以通过使用扩展来回答。这将扩展 char.Equals 以允许局部性和不区分大小写。

在扩展类中,添加以下内容:

internal static Boolean Equals(this Char src, Char ch, StringComparison comp)
{
    Return $"{src}".Equals($"{ch}", comp);
}

我目前正在工作,所以无法检查这一点,但它应该可以工作。

安迪


-4
投票

对于 caseInsensive 匹配,您可以将最后一个参数设置为 true

string.Compare(lowerCase, upperCase, true);
© www.soinside.com 2019 - 2024. All rights reserved.