Click here to Skip to main content
15,118,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I have a collection that contains numerical string, alphanumerical string and null

how I sort this collection

Data Example

{"123","562","d586","5",null,"689","a896"}

The sorted output is:- {"a896","d586","689","562","123","5"}

please help me

What I have tried:

notNullableStateroomList = notNullableStateroomList.OrderByDescending(x => x.GetType()
                                                          .GetProperty((e.Column as GridViewDataColumn).GetDataMemberName().PadLeft(x.Stateroom.Length, '0')).GetValue(x, null))
                                                          .Concat(notNullableStateroomList.Where(x => isInteger(x.Stateroom)).OrderByDescending(x => Convert.ToInt32(x.Stateroom)));
Posted
Updated 6-Jun-17 8:25am
Comments
F-ES Sitecore 6-Jun-17 9:06am
   
I can't see any order in that result. You'll need to explicitly explain what dictates the order.
Yogesh Kumar Tyagi 6-Jun-17 9:16am
   
I need to sort first all alphanumerical number in desc order than all numerical number in desc order than all null number at the end of list

It's sorting correctly: an alphabetical sort works by comparing each character in each pair of strings one by one, and the result of the whole comparison is based on the first different character in the two strings. So "1" to "9" come before "a" to "z" (which come after "A" to "Z") as that is the order in which the characters appear in the character set. After that, "100" comes before "2", "20", "43", and so on because the first difference is found in the first character.

If you want to sort these based on any numerical value, you need to use a custom comparator which splits the string into it's alphabetic and numeric components, converts the numeric data to a number (integer is probably fine) and then compares in exactly the way you describe.
Not difficult to write, if you think about the results you want carefully.
   
I would as first step take the source list out of your control before processing. Then I fetch the alphanumerical, numerical parts out and sort them each. In the end the results are combined. (Perhaps I should have a look what a custom comparator is)

void Main()
{
	
	string[] tokens = {"123","562","d586","5",null,"689","a896"};
	
	tokens.Dump(); // this is a linqpad command

    // https://stackoverflow.com/questions/7216883/linq-query-find-strings-based-upon-first-letter-b-w-two-ranges
	var start = "a";
	var end = "z";
	var regex = new Regex(string.Format("^[{0}-{1}]", start, end));
	var alphanumericalTokens = tokens
	                      .Where(x => !string.IsNullOrEmpty(x))
	                      .Where(x => regex.Match(x.ToLowerInvariant()).Success)
						  .ToList();

	var regex2 = new Regex("^[0-9]*$");
	var numericalTokens = tokens
		  		     .Where(x => !string.IsNullOrEmpty(x))
					 .Where(x => regex2.Match(x).Success)
					 .Select(int.Parse)
					 .OrderByDescending(x => x);
					 
	var numericalTokensAsStrings =  numericalTokens
               .Select(x => x.ToString()).ToList();				 

	var nullTokens = tokens
				 .Where(x => string.IsNullOrEmpty(x));

	alphanumericalTokens.Dump();
	numericalTokens.Dump();
	
	
	var mergedList = alphanumericalTokens.Union(numericalTokensAsStrings).ToList();
	mergedList.Dump();
}
   
Comments
Yogesh Kumar Tyagi 6-Jun-17 10:30am
   
could you please tell me about Dump(); the method

how I can use it in visual studio
FranzBe 6-Jun-17 10:36am
   
If you use linqpad http://www.linqpad.net/ you can use the .Dump() method to easily visualize your data. You can copy and paste the snippet above and see that it works (and modify it). If you don't use linqpad, just comment out the .Dump() calls and use the debugger instead.
I'd suggest to wite helper-class, for example:

C#
public static class StringHelper
{
	public static int ToNumeric(string value)
	{
		int retval = Int32.MinValue;

		Int32.TryParse(value, out retval);
		if(value==null && retval==0) retval = Int32.MaxValue;		
		
		return retval;
	}

	public static string TypeName(string value)
	{
		string sName = string.Empty;
		int tmp = ToNumeric(value);
		if (tmp == Int32.MaxValue)
			sName = "A";
		else if(tmp==0)
			sName = "C";
		else
			sName = "B";
				
		return sName;
	}
}


Now, you can write query:
C#
List<string> myValues = new List<string>(){"123","562","d586","5",null,"689","a896"};

var sortedList = myValues
    .OrderByDescending(x => StringHelper.TypeName(x))
    .ThenByDescending(x => StringHelper.ToNumeric(x))
    .ToList();

Result:
d586 
a896 
689 
562 
123 
5 
null 


Note: you have to improve that, because i'm bit busy today and won't assign more time over it.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900