Reputation: 105
I want to make sort list of strings which contains strings of alphabetically, mixture of alphabetic and numeric and numeric only.I have requirement from my client to sort like this:
Sort in tablelist type object contains Item Code: 111,111A,222,411G,300,411Z,G411,AG500,A111,AZ600,ABQ,ZZZ,AAN etc
Required result: First show numbers (like 111 then 222 then 300 etc...) Next will be numbers with Letters (like 111A then 411G then 411Z etc...) Next Letters with numbers (like A111 then G411 then AG500 then AZ600 etc. ...) next letters only (like AAN then ABQ then ZZZ etc....)
So the string can be anything.But I want to get sort as required result. So please help me regarding it.
Upvotes: 1
Views: 3019
Reputation: 2437
unsortedStringList.Sort(new AlphanumComparatorFastString());
AlphanumComparator:
public class AlphanumComparatorFastString : IComparer<String>
{
public int Compare(string s1, string s2)
{
if (s1 == null)
return 0;
if (s2 == null)
return 0;
int len1 = s1.Length;
int len2 = s2.Length;
int marker1 = 0;
int marker2 = 0;
// Walk through two the strings with two markers.
while (marker1 < len1 && marker2 < len2)
{
char ch1 = s1[marker1];
char ch2 = s2[marker2];
// Some buffers we can build up characters in for each chunk.
char[] space1 = new char[len1];
int loc1 = 0;
char[] space2 = new char[len2];
int loc2 = 0;
// Walk through all following characters that are digits or
// characters in BOTH strings starting at the appropriate marker.
// Collect char arrays.
do
{
space1[loc1++] = ch1;
marker1++;
if (marker1 < len1)
{
ch1 = s1[marker1];
}
else
{
break;
}
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
do
{
space2[loc2++] = ch2;
marker2++;
if (marker2 < len2)
{
ch2 = s2[marker2];
}
else
{
break;
}
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
// If we have collected numbers, compare them numerically.
// Otherwise, if we have strings, compare them alphabetically.
string str1 = new string(space1);
string str2 = new string(space2);
int result;
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
{
int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
result = str1.CompareTo(str2);
}
if (result != 0)
{
return result;
}
}
return len1 - len2;
}
}
as found on http://www.dotnetperls.com/alphanumeric-sorting
Upvotes: 3
Reputation: 1332
Try this:
var text = "111,111A,222,411G,300,411Z,G411,AG500,A111,AZ600,ABQ,ZZZ,AAN";
var list = text.Split(',').ToList();
var result = list.OrderBy(i => i, new StringCompare());
foreach (var item in result)
{
Console.WriteLine(item);
}
StringCompare class:
class StringCompare : IComparer<string>
{
string[] exps = new[] { @"^\d+$", @"^\d+[a-zA-Z]+$", @"^[a-zA-Z]\d+$", @"^[a-zA-Z]+\d+$" };
public int Compare(string x, string y)
{
for (int i = 0; i < exps.Length; i++)
{
var isNumberx = Regex.IsMatch(x, exps[i]);
var isNumbery = Regex.IsMatch(y, exps[i]);
if (isNumberx && isNumbery)
return string.Compare(x, y);
else if (isNumberx)
return -1;
else if (isNumbery)
return 1;
//return string.Compare(x, y);
}
return string.Compare(x, y);
}
}
You will get:
111
222
300
111A
411G
411Z
A111
G411
AG500
AZ600
AAN
ABQ
ZZZ
Upvotes: 2