Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom array sort

Tags:

arrays

c#

.net

Each item/string in my array starts with two letters followed by two or three numbers and then sometimes followed by another letter.

Examples, RS01 RS10 RS32A RS102 RS80 RS05A RS105A RS105B

I tried to sort this using the default Array.Sort but it came back with this...

RS01
RS05A
RS10
RS102
RS105A
RS105B
RS32A
RS80

But I need it like this..

RS01
RS05A
RS10
RS32A
RS80
RS102
RS105A
RS105B

Any Ideas?

like image 794
Sammy Avatar asked Jan 21 '26 20:01

Sammy


1 Answers

Here is sorting with custom comparison delegate and regular expressions:

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 (little refactoring, and moving all stuff to separate comparer class). Usage:

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

Comparer itself:

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);
        }
    }
}
like image 131
Sergey Berezovskiy Avatar answered Jan 24 '26 13:01

Sergey Berezovskiy