排序字符串数字

Kar*_*arl 9 c# sorting string list

可能重复:
C#中的自然排序顺序

我有一个包含大量数字的列表.但是由于一些额外的字母,它们被保存为字符串.

我的列表看起来像这样:

1
10
11
11a
11b
12
2
20
21a
21c
A1
A2
...
Run Code Online (Sandbox Code Playgroud)

但它应该是这样的

1
2
10
11a
11b
...
A1
A2
...
Run Code Online (Sandbox Code Playgroud)

如何对列表进行排序以获得此结果?

Ric*_*ard 15

按照之前的评论,我还将实现一个自定义IComparer<T>类.根据我的收集,项目的结构可以是数字,也可以是数字后跟字母的组合.如果是这种情况,则以下IComparer<T>实现应该有效.

public class CustomComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var regex = new Regex("^(d+)");

        // run the regex on both strings
        var xRegexResult = regex.Match(x);
        var yRegexResult = regex.Match(y);

        // check if they are both numbers
        if (xRegexResult.Success && yRegexResult.Success)
        {
            return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value));
        }

        // otherwise return as string comparison
        return x.CompareTo(y);
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个IComparer<T>,你就可以整理你的列表string

var myComparer = new CustomComparer();
myListOfStrings.Sort(myComparer);
Run Code Online (Sandbox Code Playgroud)

已经使用以下项目进行了测试:

2, 1, 4d, 4e, 4c, 4a, 4b, A1, 20, B2, A2, a3, 5, 6, 4f, 1a

并给出结果:

1, 1a, 2, 20, 4a, 4b, 4c, 4d, 4e, 4f, 5, 6, A1, A2, a3, B2

  • 我相信正则表达式应该是`^(\\d+)`。更好的是,Regex 可以只是`(\\d+)` 来处理`Region 1, Region 10, Region 2` 以及`1, 10, 2`。 (2认同)

L.B*_*L.B 6

由于这包括许多字符串操作、正则表达式等,我认为它不是一种有效的算法,但它似乎有效。

List<string> list1 = new List<string>() { "11c22", "1", "10", "11", "11a", "11b", "12", "2", "20", "21a", "21c", "A1", "A2" };
List<string> list2 = new List<string>() { "File (5).txt", "File (1).txt", "File (10).txt", "File (100).txt", "File (2).txt" };
var sortedList1 = NaturalSort(list1).ToArray();
var sortedList2 = NaturalSort(list2).ToArray();
Run Code Online (Sandbox Code Playgroud)
public static IEnumerable<string> NaturalSort(IEnumerable<string> list)
{
    int maxLen = list.Select(s => s.Length).Max();
    Func<string, char> PaddingChar = s => char.IsDigit(s[0]) ? ' ' : char.MaxValue;

    return list
            .Select(s =>
                new
                {
                    OrgStr = s,
                    SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, PaddingChar(m.Value)))
                })
            .OrderBy(x => x.SortStr)
            .Select(x => x.OrgStr);
}
Run Code Online (Sandbox Code Playgroud)

  • 这很好用!谢谢你! (2认同)