自定义数组排序

本文关键字:数组排序 自定义 | 更新日期: 2023-09-27 18:00:24

数组中的每个项/字符串都以两个字母开头,后面跟着两三个数字,有时还会跟着另一个字母。

示例,RS01 RS10 RS32A RS102 RS80 RS05A RS105A RS105B

我试着用默认的数组对它进行排序。排序结果是。。。

RS01
RS05A
RS10
RS102
RS105A
RS105B
RS32A
RS80

但我需要这样。。

RS01
RS05A
RS10
RS32A
RS80
RS102
RS105A
RS105B

有什么想法吗?

自定义数组排序

下面是使用自定义比较委托和正则表达式进行排序:

string[] array = { "RS01", "RS10", "RS32A", "RS102", 
                   "RS80", "RS05A", "RS105A", "RS105B" };
Array.Sort(array, (s1, s2) =>
    {
        Regex regex = new Regex(@"([a-zA-Z]+)('d+)([a-zA-Z]*)");
        var match1 = regex.Match(s1);                                        
        var match2 = regex.Match(s2);
        // prefix
        int result = match1.Groups[1].Value.CompareTo(match2.Groups[1].Value);
        if (result != 0)
            return result;
        // number 
        result = Int32.Parse(match1.Groups[2].Value)
                        .CompareTo(Int32.Parse(match2.Groups[2].Value));
        if (result != 0)
            return result;
        // suffix
        return match1.Groups[3].Value.CompareTo(match2.Groups[3].Value);
    });

UPDATE(少量重构,并将所有内容移动到单独的comparer类)。用法:

Array.Sort(array, new RSComparer());

比较器本身:

public class RSComparer : IComparer<string>
{
    private Dictionary<string, RS> entries = new Dictionary<string, RS>();
    public int Compare(string x, string y)
    {
        if (!entries.ContainsKey(x))
            entries.Add(x, new RS(x));
        if (!entries.ContainsKey(y))
            entries.Add(y, new RS(y));
        return entries[x].CompareTo(entries[y]);
    }
    private class RS : IComparable
    {
        public RS(string value)
        {
            Regex regex = new Regex(@"([A-Z]+)('d+)([A-Z]*)");
            var match = regex.Match(value);
            Prefix = match.Groups[1].Value;
            Number = Int32.Parse(match.Groups[2].Value);
            Suffix = match.Groups[3].Value;
        }
        public string Prefix { get; private set; }
        public int Number { get; private set; }
        public string Suffix { get; private set; }
        public int CompareTo(object obj)
        {
            RS rs = (RS)obj;
            int result = Prefix.CompareTo(rs.Prefix);
            if (result != 0)
                return result;
            result = Number.CompareTo(rs.Number);
            if (result != null)
                return result;
            return Suffix.CompareTo(rs.Suffix);
        }
    }
}

您可以使用以下linq查询:

var strings = new[] { 
    "RS01","RS05A","RS10","RS102","RS105A","RS105B","RS32A","RS80"
};
strings = strings.Select(str => new
{
    str,
    num = int.Parse(String.Concat(str.Skip(2).TakeWhile(Char.IsDigit))),
    version = String.Concat(str.Skip(2).SkipWhile(Char.IsDigit))
})
.OrderBy(x => x.num).ThenBy(x => x.version)
.Select(x => x.str)
.ToArray();

演示

结果:

RS01
RS05A
RS10
RS32A
RS80
RS102
RS105A
RS105B

您需要编写一个实现IComparer<string>的自定义比较器类;将字符串分解为组件非常简单。当你调用Array.Sort时,给它一个比较器的实例,你就会得到你想要的结果。