简体   繁体   English

区分大小写的字符串比较

[英]case-sensitive string comparison

I want to sort strings case sensitive: so that if one starts with capital "C" then it should be "bigger" (for example) than the one that starts with "c" but also smaller than the one that starts with "d". 我想对字符串区分大小写:如果一个以大写“C”开头,那么它应该比以“c”开头但比小于以“d”开头的那个“更大”(例如)。 。

For example, sorted list: "a", "A", "chi", "Che", "Chr" 例如,排序列表:“a”,“A”,“chi”,“Che”,“Chr”

It is written that String comparison methods are case sensitive by default. 编写的字符串比较方法默认区分大小写。 But it looks like my understanding of "case sensitive" differs from the default one. 但看起来我对“区分大小写”的理解与默认情况不同。

Neither of default methods I tried ( String.CompareTo , String.Compare (with different StringComparison values)) gives result I want. 我尝试过的默认方法( String.CompareToString.Compare (具有不同的StringComparison值))都没有给出我想要的结果。

Here is the code I've used for testing: 这是我用于测试的代码:

using System;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        var list = new List<String> { "Che", "Chr", "chi", "a", "A" }; 

        // Any other way to sort goes here
        list.Sort((s1, s2) => s1.CompareTo(s2));

        for (var i = 0; i < list.Count; i++)
        {
            Console.WriteLine(list[i]);
        }
    }
}

Exactly this code gives the result: "a" "A" "Che" "chi" "Chr". 这个代码恰好给出了结果:“a”“A”“Che”“chi”“Chr”。 So small "c" is standing between to "C"s. 这么小的“c”站在“C”之间。

So, the question is: is there any way to achieve the sort order I want (which looks pretty obvious) with any of default methods, without writing my own comparer? 所以,问题是:有没有办法用任何默认方法实现我想要的排序顺序(看起来非常明显),而无需编写我自己的比较器? Am I missing something? 我错过了什么吗?

I don't see other way than writing own comparer because of non-strait logic in terms of string: a < A < c < C = 97 < 65 < 99 < 67 . 我没有看到除写自己的比较器之外的其他方式,因为字符串方面的非海峡逻辑: a < A < c < C = 97 < 65 < 99 < 67

sealed class CustomComparer : Comparer<string>
{
    public override int Compare(string x, string y)
    {
        for (int i = 0; i < Math.Min(x.Length, y.Length); i++)
        {
            char xc = x[i];
            char yc = y[i];
            if (xc == yc)
                continue;
            char xcLow = char.ToLowerInvariant(xc);
            char ycLow = char.ToLowerInvariant(yc);
            if (xcLow == ycLow)
                return xc < yc ? 1 : -1;
            else
                return xcLow < ycLow ? -1 : 1;
        }
        return x.Length.CompareTo(y.Length);
    }
}

Usage: 用法:

var list = new List<String> { "Che", "Chr", "chi", "a", "A" };
list.Sort(new CustomComparer()); // a, A, chi, Che, Chr

It sounds like you want to sort by first letter (case sensitive) then by the rest of the word (Case-insensitive). 听起来你想按首字母(区分大小写)排序,然后按字母的其余部分排序(不区分大小写)。 If that's the case, I'd use something like the following LINQ: 如果是这种情况,我会使用类似下面的LINQ:

list.OrderBy (l => l.Substring(0,1)).ThenBy (l => l.ToLower())

Result: a A chi Che Chr 结果:A chi Che Chr

This comparer seems to do what you are looking for.. 这个比较器似乎做你想要的..

class MyComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var sets = x.ToCharArray().Zip(y.ToCharArray(), 
                  (LeftChar, RightChar) => new { LeftChar, RightChar });
        var charsToCompare = sets.FirstOrDefault(c => c.LeftChar != c.RightChar);
        if (charsToCompare == null)
            return 0;
        var lowers = char.ToLower(charsToCompare.LeftChar).CompareTo(char.ToLower(charsToCompare.RightChar));
        if (lowers == 0)
            return charsToCompare.RightChar.CompareTo(charsToCompare.LeftChar);
        else
            return char.ToUpper(charsToCompare.LeftChar).CompareTo(char.ToUpper(charsToCompare.RightChar));
    }
}

Tested with 经过测试

public class Test
{
    public static void Main()
    {
        var list = new List<String> { "Che", "Chr", "chi", "a", "A" };

        // Any other way to sort goes here
        list.Sort(new MyComparer());
       // list.Sort((s1, s2) => s1.CompareTo(s2));

        for (var i = 0; i < list.Count; i++)
        {
            Console.WriteLine(list[i]);
        }
        Console.ReadKey();
    }
}



Output

a
A
chi
Che
Chr

You should use this method for sorting strings 您应该使用方法来排序字符串

string.Compare instead of a.CompareTo . string.Compare而不是a.CompareTo

String.Compare("Foo", "foo", StringComparison.InvariantCulture)

will return true, giving you the sort order you desire. 将返回true,为您提供所需的排序顺序。

Applied to your example: 适用于您的示例:

list.Sort((s1, s2) => string.Compare(s1, s2, StringComparison.InvariantCulture));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM