-2

I am attempting to sort a List of fuses by the Designator property of the fuse.

The Fuse Model:

public class Fuse
{
    public string Designator { get; set; }

    public string Rating { get; set; }

    public string Type { get; set; }
}

Example Data

This is an example of what a list of fuses would look like.

enter image description here

What I have tried:

fuses = fuses.OrderBy(f => f.Designator).ToList();

The above code sort of works, but it puts the F10 before F2. Does anyone know of a way to sort a List by the designator appropriately? I have read about natural sorting algorithms but not quite sure how to apply them correctly.

Any help would be greatly appreciated.

Thank you,

Selthien
  • 1,178
  • 9
  • 33
  • 2
    https://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp – Michael Liu Sep 26 '18 at 19:05
  • 2
    you would need to parse the property into a sortable weight using a comparer to get the desired behavior. currently it is sorting it as a string. where 10, comes before 2 – Nkosi Sep 26 '18 at 19:05
  • 2
    It seems like a somewhat specific string comparison, first taking the letter then comparing by the parsed number afterwards. For cases like these, I'd suggest creating a custom IComparer and using it in an OrderBy overload. – Alice Sep 26 '18 at 19:06
  • 1
    Would it be possible for a example implementation of this? – Selthien Sep 26 '18 at 19:08
  • Is the `Designator` code a fixed format? Always 1 letter A-Z + a whole number? – Igor Sep 26 '18 at 19:10
  • Yes, it is actually Always F + whole numbers. Sometimes could appear as F1,F2,F3 or F1-F3. Also, fuses can't repeat, you would never have a situation like F1-F3 and F3-F5. – Selthien Sep 26 '18 at 19:12
  • @Selthien Did you check the link in the first comment? – 41686d6564 stands w. Palestine Sep 26 '18 at 19:12
  • 2
    Do you always want to sort based on the first `Designator` value in the range? – Igor Sep 26 '18 at 19:13
  • @Igor yes that is correct. I checked the first link but not quite sure how to implement it with a List. Makes sense if you want to compare two strings. – Selthien Sep 26 '18 at 19:14
  • [Alphanumeric sorting using LINQ](https://stackoverflow.com/questions/5093842/alphanumeric-sorting-using-linq) – Nkosi Sep 26 '18 at 19:18
  • @Selthien The first link **does have your answer**, you just need to pass an instance of the comparer class to the `OrderBy` method. [Here's a complete example](https://dotnetfiddle.net/wyocn3). – 41686d6564 stands w. Palestine Sep 26 '18 at 19:20

3 Answers3

1

If you only compare string F2 the order will greater than F10.

You can try to order by number by Regex.

use ^F(\d+) pattern to get the number then order by.

fuses = fuses.OrderBy(f => int.Parse(Regex.Match(f.Designator, @"^F(\d+)").Groups[1].Value)).ToList();
D-Shih
  • 44,943
  • 6
  • 31
  • 51
0

You could implement IComparable<T>

class Fuse : IComparable<Fuse>
{
    public string Designator { get; set; }

    public int CompareTo(Fuse other)
    {
        if (string.IsNullOrWhiteSpace(other?.Designator)) return -1;
        if (string.IsNullOrWhiteSpace(this.Designator)) return 1;
        if (this.Designator == other.Designator) return 0;

        // get the first item in the range
        var d1Str = this.Designator.Split(new[] {',', '-'})[0];
        var d2Str = other.Designator.Split(new[] {',', '-'})[0];

        // parse to int
        var d1 = int.Parse(d1Str.Substring(1));
        var d2 = int.Parse(d2Str.Substring(1));

        return d1 > d2 ? 1 : -1;
    }
}

Test code

var list = new List<Fuse>()
{
    new Fuse{Designator = "F8,F9"},
    new Fuse{Designator = "F1,F2,F3"},
    new Fuse{Designator = "F10-F12"},
    new Fuse{Designator = "F4-F7"},
};

foreach (var itm in list.OrderBy(_ => _))
{
    Console.WriteLine(itm.Designator);
}

Console.ReadLine();

Output

F1,F2,F3
F4-F7
F8,F9
F10-F12
Igor
  • 60,821
  • 10
  • 100
  • 175
-1

You can try to sort it by integer instead. Throw away first letter, parse as integer and sort by this integer.

f => Int32.Parse(f.Designator.Substring(1))

Of course you can always refactor it out of lambda into something else.

Ebuall
  • 1,306
  • 1
  • 12
  • 14