排序包含数字和字母的字符串

本文关键字:字符串 包含 数字 排序 | 更新日期: 2023-09-27 17:49:24

我需要排序一个场景数字列表,它实际上是一个字符串列表,包含数字和字母。

这是列表

101-11
102-1
101-10
101-8
103-10
101-8A
101-9
103-4
103-4B

我做了一个比较器

public class SceneComparer : IComparer
{
    private readonly Regex sceneRegEx = new Regex(@"('D*)('w*)", RegexOptions.Compiled);
    public int Compare(object x, object y)
    {
        Scene sceneX = x as Scene;
        Scene sceneY = y as Scene;
        var firstSceneMatch = this.sceneRegEx.Match(sceneX.SceneNumber);
        var firstSceneNumeric = Convert.ToInt32(firstSceneMatch.Groups[1].Value);
        var firstSceneAlpha = firstSceneMatch.Groups[2].Value;
        var secondSceneMatch = this.sceneRegEx.Match(sceneY.SceneNumber);
        var secondSceneNumeric = Convert.ToInt32(secondSceneMatch.Groups[1].Value);
        var secondSceneAlpha = secondSceneMatch.Groups[2].Value;
        if (firstSceneNumeric < secondSceneNumeric)
        {
            return -1;
        }
        if (firstSceneNumeric > secondSceneNumeric)
        {
            return 1;
        }
        return string.CompareOrdinal(firstSceneAlpha, secondSceneAlpha);            
    }
}

得到以下结果

101-8
101-8A
101-9
102-1
103-4
103-4B
101-10
101-11
103-10

看起来它只对破折号之前的第一个数字和字母数字进行排序,但它不会对破折号之后的数字进行排序以获得以下所需的结果。

101-8
101-8A
101-9
101-10
101-11
102-1    
103-4
103-4B
103-10

如何得到想要的结果。

排序包含数字和字母的字符串

您必须对字符串进行Split并提取其中的数字以请求对这些字段进行排序。

// Assuming you have this...
List<string> list = new List<string>()
{
    "101-11",
    "102-1",
    "101-10",
    "101-8",
    "103-10",
    "101-8A",
    "101-9",
    "103-4",
    "103-4B"
};

// You could do this.
var result = list.Select(x=>
    {
        var splits = x.Split('-');
        return new 
        {
            first = int.Parse(splits[0]),
            second = int.Parse(Regex.Match(splits[1], @"'d+").Value),
            item =x
        };
    })
    .OrderBy(x=>x.first)
    .ThenBy(x=>x.second)
    .Select(x=>x.item)
    .ToList(); 

Check this Demo

你很接近了。用Matches代替Match

此外,更正您的Regex,因为'D捕获非数字字符。

public class SceneComparer : IComparer
{
    private readonly Regex sceneRegEx = new Regex(@"('d+)('w+)?", RegexOptions.Compiled);
    public int Compare(object x, object y)
    {
        Scene sceneX = x as Scene;
        Scene sceneY = y as Scene;
        var firstSceneMatches = this.sceneRegEx.Matches(sceneX.SceneNumber);
        var secondSceneMatches = this.sceneRegEx.Matches(sceneY.SceneNumber);
        var matchesCount = Math.Min(firstSceneMatches.Count, secondSceneMatches.Count);
        for (var i = 0; i < matchesCount; i++)
        {
            var firstSceneMatch = firstSceneMatches[i];
            var secondSceneMatch = secondSceneMatches[i];
            var firstSceneNumeric = Convert.ToInt32(firstSceneMatch.Groups[1].Value);
            var secondSceneNumeric = Convert.ToInt32(secondSceneMatch.Groups[1].Value);
            if (firstSceneNumeric != secondSceneNumeric)
            {
                return firstSceneNumeric - secondSceneNumeric;
            }
            var firstSceneAlpha = firstSceneMatch.Groups[2].Value;
            var secondSceneAlpha = secondSceneMatch.Groups[2].Value;
            if (firstSceneAlpha != secondSceneAlpha)
            {
                return string.CompareOrdinal(firstSceneAlpha, secondSceneAlpha);
            }
        }
        return firstSceneMatches.Count - secondSceneMatches.Count;
    }
}