0

I have an array list that comprises of elements like: M1,M2,M3...M9,M10,M11 so on. When I sorted the elements using built in sorting feature, M10 and M11 get placed in 2nd and 3rd position respectively after M1.

Is there anyway to sort where I need M10 and M11 to come after M9?

Anjan Kant
  • 4,090
  • 41
  • 39
user9683713
  • 185
  • 2
  • 13

5 Answers5

1

similar kind of question and some accepted solutions can be found in below link

c# linq orderby numbers that are string (and you cannot convert them to int)

Tony Tom
  • 1,435
  • 1
  • 10
  • 17
0

You can use IComparable to implement custom sorting for your class. Basicaly, IComparable allows custom sorting of objects when implemented.

Just check the following Example:

class Employee : IComparable<Employee>
{
public int Salary { get; set; }
public string Name { get; set; }

public int CompareTo(Employee other)
{
    // Alphabetic sort if salary is equal. [A to Z]
    if (this.Salary == other.Salary)
    {
        return this.Name.CompareTo(other.Name);
    }
    // Default to salary sort. [High to low]
    return other.Salary.CompareTo(this.Salary);
}
}

Regards.

leandro.andrioli
  • 997
  • 5
  • 12
0

What you are trying to do is called Natural sort
There is a NuGet package for .Net implementation

Then you can sort your array very easy

arr.OrderBy(x => x, StringComparer.OrdinalIgnoreCase.WithNaturalSort());
hessam hedieh
  • 780
  • 5
  • 18
0

Here you are, without any external packages:

     class Program
  {
    static void Main(string[] args)
    {
      // Initializing your list of strings
      List<string> list = new List<string>()
      {
        "M9", "M2", "M7", "M11", "M5", "M6", "M3", "M8", "M1", "M10", "M4", "M12"
      };

      SortStringList(list);
    }

    private static void SortStringList(List<string> list)
    {
      // Bubble sort
      bool change = true;

      while (change)
      {
        change = false;
        for (int i = 0; i < list.Count; i++)
        {
          if (i + 1 < list.Count)
          {
            // here im converting the string to a number removing the first char "M"
            int currentElement = Convert.ToInt32(list[i].Remove(0, 1));
            int nextElement = Convert.ToInt32(list[i + 1].Remove(0, 1));
            // comparing two integers and swapping the strings elements
            if (currentElement > nextElement)
            {
              string tmp = list[i];
              list[i] = list[i + 1];
              list[i + 1] = tmp;
              change = true;
            }
          }
        }
      }
    }
  }
Dave
  • 1,912
  • 4
  • 16
  • 34
0

OrderBy with custom IComparer could be useful. Try this:

var list = new List<string> { "M10", "M2", "M9", "M1", "M22" };
Console.WriteLine(string.Join(", ", list.OrderBy(_ => _, new Comparer())));
// M1, M2, M9, M10, M22

Where custom IComparer<string> could be implemented like this:

class Comparer : IComparer<string>
{
    public int Compare(string x, string y) 
        => x.Length != y.Length ? x.Length - y.Length : string.Compare(x, y);
}
Johnny
  • 8,939
  • 2
  • 28
  • 33