Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 858
  • Last Modified:

Sort a List<String> in numeric order in silverlight

I have a List<String> in a SL4 app that I invoke the sort() method, so sort the items in order. This works great on alphnumeric characters, but I need to store the strings as numeric values.

If I have a List<String> with strings "1", "2", "10", the sort will sort as

1
10
2

I need to sort this in numeric order, can anyone help out with this in Silverlight.

Thanks
0
wint100
Asked:
wint100
  • 7
  • 4
  • 2
1 Solution
 
Todd GerbertIT ConsultantCommented:
Why not a List<int> instead?
0
 
wint100Author Commented:
The list actually holds a list of filenames (ie 1.jpg), so it has to stay as string as the name could be anything.
0
 
Todd GerbertIT ConsultantCommented:
I figured something like that would probably be the case, but when I make an assumption I usually end up dead-wrong, so I thought I'd better ask. ;)

Are the filenames always some numeric characters followed by a dot and an extension?  That is, you don't ever have filenames without numbers in the list - or filenames like 123_SomeOtherText.jpg - do you?
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
wint100Author Commented:
No the name can be anything, it just so happens this particular case has a list of files named with only a number, which made me notice the issue with sorting.
0
 
Todd GerbertIT ConsultantCommented:
Are you just concerned about file names that start with a number? I've got  an idea for the case where numbers appear in the middle of a string, but more than one group of numbers separated by letters might get a little  tricky.
0
 
wint100Author Commented:
How would that work if the files were:

File1.jpg
File2.jpg
File10.jpg

The files should be un the order above but I think the File10.jpg would be put second.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
This examples uses the first number found in the filename to do the comparisons.  A filename with a number will always come before a filename with NO number.  If neither filename has a number in it then a straight string comparison is used.

Add "using System.Text.RegularExpressions;" to the top of your code:

private void Foo()
        {
            string[] FileNames = System.IO.Directory.GetFiles(@"C:\Users\Mike\Pictures\Wallpaper", "*.jpg");
            Array.Sort(FileNames, NumericFileSorter);
            foreach (string FileName in FileNames)
                Console.WriteLine(FileName);
        }

        private int NumericFileSorter(string File1, string File2)
        {
            int result = 0;
            int Num1, Num2;
            Match Match1, Match2;
            Match1 = Regex.Match(File1, @"\d+");
            Match2 = Regex.Match(File2, @"\d+");
            if (Match1.Success)
            {
                if (Match2.Success)
                {
                    // both File1 and File2 had a number...convert them to ints
                    if (int.TryParse(Match1.ToString(), out Num1) && int.TryParse(Match2.ToString(), out Num2))
                    {
                        // numbers successfully converted to ints...do the NUMERIC comparison
                        result = Num1.CompareTo(Num2);
                    }
                    else
                    {
                        // something went wrong with the parse...default to string comparison
                        result = File1.CompareTo(File2);
                    }
                }
                else
                {
                    // File1 had a number but File2 did not
                    result = -1;
                }
            }
            else
            {
                if (Match2.Success)
                {
                    // File2 had a number but File1 did not
                    result = 1;
                }
                else
                {
                    // neither File1 or File2 had a number...just do a string comparison
                    result = File1.CompareTo(File2);
                }
            }
            return result;
        }

Open in new window

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
*The example was for C# WinForms and an Array.  It would be very similar for a List<string>...just use YourListName.Sort(NumericFileSorter).  Hopefully you'll know how to use it in a Silverlight app.
0
 
Todd GerbertIT ConsultantCommented:
My idea is similar, using a custom sorting function...but using Regex to pull numeric digits, parse them into an Int32, then put it back into the string with leading zero's for the sake of comparison.  That way File1.jpg, File2.jpg and File10.jpg would (just for the sake of sorting, without changing the original strings) sort as File00000001.jpg, File00000002.jpg and File00000010.jpg.

Usage:
List<string> files = new List<string>(new string[] { "NoNumbers.jpg", "File1.jpg", "File3.jpg", "File10.jpg", "File2.jpg" });
NumericStringListSorter.Sort(files);

Open in new window


The NumericStringListSorter:
public class NumericStringListSorter
{
	private static Regex regex = new Regex(@"\d{1,7}");

	public static void Sort(List<string> list)
	{
		list.Sort(delegate(string x, string y)
		{
			if (x == null && y == null)
				return 0;
			else if (x == null && y != null)
				return -1;
			else if (x != null && y == null)
				return 1;
			else
			{
				x = regex.Replace(x, (Match m) => Int32.Parse(m.Value).ToString("D8"));
				y = regex.Replace(y, (Match m) => Int32.Parse(m.Value).ToString("D8"));

				return x.CompareTo(y);
			}
		});
	}
}

Open in new window

0
 
Todd GerbertIT ConsultantCommented:
Of course, that example assumes there won't be any number groups larger than 9999999, but you could adjust the regex and possibly use a data type larger than Int32, with some overflow-checking.
0
 
Todd GerbertIT ConsultantCommented:
I guess that could be shortened up a bit...

public static void Sort(List<string> list)
{
	list.Sort(delegate(string x, string y)
	{
		if (x == null || y == null)
			return String.Compare(x, y);
		else
		{
			x = regex.Replace(x, (Match m) => Int32.Parse(m.Value).ToString("D8"));
			y = regex.Replace(y, (Match m) => Int32.Parse(m.Value).ToString("D8"));

			return x.CompareTo(y);
		}
	});
}

Open in new window

0
 
wint100Author Commented:
The last post looks good, I'm just testing now. I found the following article, but doubt it can be applied easily to Silverlight, what do you think:

http://www.codeproject.com/KB/recipes/csnsort.aspx
0
 
Todd GerbertIT ConsultantCommented:
The code in that article will probably run in Silverlight without change, but it looks awfully convoluted.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now