Solved

Sort a List<String> in numeric order in silverlight

Posted on 2011-02-15
13
800 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
  • 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
 
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 85

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 85

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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
LINQ question 7 22
Converting C# Objects into JSON file 7 41
cs.Designer Issue 2 19
Showdialog 8 21
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now