Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# ordering strings with different formats

Tags:

c#

.net

linq

I have Licence plate numbers which I return to UI and I want them ordered in asc order:

So let's say the input is as below:

1/12/13/2
1/12/11/3
1/12/12/2
1/12/12/1

My expected output is:

1/12/11/3
1/12/12/1
1/12/12/2
1/12/13/2

My current code which is working to do this is:

var orderedData = allLicenceNumbers
   .OrderBy(x => x.LicenceNumber.Length)
   .ThenBy(x => x.LicenceNumber)
   .ToList();

However for another input sample as below:

4/032/004/2
4/032/004/9
4/032/004/3/A
4/032/004/3/B
4/032/004/11

I am getting the data returned as:

4/032/004/2
4/032/004/9
4/032/004/11
4/032/004/3/A
4/032/004/3/B

when what I need is:

4/032/004/2
4/032/004/3/A
4/032/004/3/B
4/032/004/9
4/032/004/11

Is there a better way I can order this simply to give correct result in both sample inputs or will I need to write a custom sort?

EDIT

It wont always be the same element on the string.

This could be example input:

2/3/5/1/A
1/4/6/7
1/3/8/9/B
1/3/8/9/A
1/5/6/7

Expected output would be:

1/3/8/9/A
1/3/8/9/B
1/4/6/7
1/5/6/7
2/3/5/1/A
like image 464
Ctrl_Alt_Defeat Avatar asked Sep 10 '26 10:09

Ctrl_Alt_Defeat


1 Answers

You should split your numbers and compare each part with each other. Compare numbers by value and strings lexicographically.

var licenceNumbers = new[]
{
    "4/032/004/2",
    "4/032/004/9",
    "4/032/004/3",
    "4/032/004/3/A",
    "4/032/004/3/B",
    "4/032/004/11"
};

var ordered = licenceNumbers
    .Select(n => n.Split(new[] { '/' }))
    .OrderBy(t => t, new LicenceNumberComparer())
    .Select(t => String.Join("/", t));

Using the following comparer:

public class LicenceNumberComparer: IComparer<string[]>
{ 
    public int Compare(string[] a, string[] b)
    {
        var len = Math.Min(a.Length, b.Length);
        for(var i = 0; i < len; i++)
        {
            var aIsNum = int.TryParse(a[i], out int aNum);
            var bIsNum = int.TryParse(b[i], out int bNum);
            if (aIsNum && bIsNum)
            {
                if (aNum != bNum)
                {
                    return aNum - bNum;
                }
            }
            else
            {
                var strCompare = String.Compare(a[i], b[i]);
                if (strCompare != 0)
                {
                    return strCompare;
                }
            }
        }
        return a.Length - b.Length;
    }
}
like image 193
hansmaad Avatar answered Sep 12 '26 04:09

hansmaad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!