Solved

Sort a List<String> in numeric order in silverlight

Posted on 2011-02-15
13
836 Views
Last Modified: 2012-05-11
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
Comment
Question by:wint100
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
  • 2
13 Comments
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34900304
Why not a List<int> instead?
0
 
LVL 1

Author Comment

by:wint100
ID: 34900333
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
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34900534
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
Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

 
LVL 1

Author Comment

by:wint100
ID: 34900573
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
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34900676
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
 
LVL 1

Author Comment

by:wint100
ID: 34900763
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
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 34901399
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
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 34901451
*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
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34901782
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
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34901870
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
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 500 total points
ID: 34901958
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
 
LVL 1

Author Comment

by:wint100
ID: 34904504
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
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34906250
The code in that article will probably run in Silverlight without change, but it looks awfully convoluted.
0

Featured Post

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question