Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Tuesday, April 8, 2014 3:18 PM
Hi All,
I will be highly obliged if you could solve my issue.
The issue which I am facing that is about the sorting order of the Special Chars, Numbers and Alphbets.
I think default sorting is Special Chars -> Numbers -> Alphbets in Ascending order. Suppose I have below data
"Test1","12234","23","@abc","@123"
if we sort the above data in c# in ascending order then we will get the following result
"@123","@abc","12234","23","test1"
But as per my requirement , I want the sorting to be Numbers -> Special Chars ->Alphabets
The above result should come as
"12234","23","@123","@abc","test1"
And these results I am displaying in the DataGrid, So I want to change the way of default sorting of the grid so that the above result can be achieved.
Thanks in advance.
All replies (3)
Tuesday, April 8, 2014 4:07 PM âś…Answered
There are overloads to List<>.Sort()
that accepts custom comparers.
You can also substitue a lambda for an IComparer. This is handy for cases like this where you want a one-off sort. If this isn't a one-off, you're probably better off with a custom IComparer class. Here's how you'd do this brute force style:
List<string> list = new List<string>() { "Test1", "12234", "23", "@abc", "@123" };
list.Sort((x, y) =>
{
if (!Char.IsLetterOrDigit(x[0]))
{
if (Char.IsLetter(y[0]))
return -1;
else if (Char.IsDigit(y[0]))
return 1;
}
return x.CompareTo(y);
});
foreach (var s in list)
Console.WriteLine(s);
output
12234
23
@123
@abc
Test1
Hope this helps.
Tuesday, April 8, 2014 4:04 PM
But as per my requirement , I want the sorting to be Numbers -> Special Chars ->Alphabets
You can use Linq to perform custom sorting based on your requirement. This could be optimized or modified. But, here is an initial example to begin with
using System.Linq;
using System.Collections.Generic;
var input = new string[] { "12234", "23", "@123", "@abc", "test1" };
var output = new List<string>();
int value = 0;
//order numbers
output.AddRange(input.Where(a => int.TryParse(a, out value)).OrderBy(a => int.Parse(a)).ToList());
//order special characters
output.AddRange(input.Where(a => !char.IsLetterOrDigit(a[0])).OrderBy(a => a));
//order string
output.AddRange(input.Where(a => char.IsLetter(a[0])).OrderBy(a => a));
Tuesday, April 8, 2014 4:25 PM
You can write your own custom comparer:
public class CustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int compare = 0;
if (Char.IsNumber(x[0]) && (Char.IsLetter(y[0])|| !Char.IsLetterOrDigit(y[0])))
compare = -1;
if (Char.IsLetter(x[0]) && (Char.IsNumber(y[0]) || !Char.IsLetterOrDigit(y[0])))
compare = 1;
if (!Char.IsLetterOrDigit(x[0]) && Char.IsLetter(y[0]))
compare = -1;
if (!Char.IsLetterOrDigit(x[0]) && Char.IsNumber(y[0]))
compare = 1;
return compare;
}
}
Then you can pass that in to the the OrderBy method:
var input = new[] { "Test1", "12234", "23", "@abc", "@123" };
foreach (var i in input.OrderBy(s => s, new CustomComparer()))
{
Console.WriteLine(i);
}
[EDIT]
There's a bug in my algorithm. If you want a custom comparer class, replace the body of my Compare method with Smirnov's (correct) implementation.