Home
Manage Your Code
Snippet: Natural Sort Comparer (C#)
Title: Natural Sort Comparer Language: C#
Description: This can be used to sort string collections based on a natural sort. Views: 550
Author: Justin Jones Date Added: 12/27/2007
Copy Code  
1using System;
2using System.Collections.Generic;
3using System.Text.RegularExpressions;
4
5public class NaturalComparer : Comparer<string>, IDisposable
6{
7	private Dictionary<string, string[]> table;
8
9	public NaturalComparer()
10	{
11		table = new Dictionary<string, string[]>();
12	}
13
14	public void Dispose()
15	{
16		table.Clear();
17		table = null;
18	}
19
20	public override int Compare(string x, string y)
21	{
22		if(x == y)
23		{
24			return 0;
25		}
26		string[] x1, y1;
27		if(!table.TryGetValue(x, out x1))
28		{
29			x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
30			table.Add(x, x1);
31		}
32		if(!table.TryGetValue(y, out y1))
33		{
34			y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");
35			table.Add(y, y1);
36		}
37
38		for(int i = 0; i < x1.Length && i < y1.Length; i++)
39		{
40			if(x1[i] != y1[i])
41			{
42				return PartCompare(x1[i], y1[i]);
43			}
44		}
45		if(y1.Length > x1.Length)
46		{
47			return 1;
48		}
49		else if(x1.Length > y1.Length)
50		{
51			return -1;
52		}
53		else
54		{
55			return 0;
56		}
57	}
58
59	private static int PartCompare(string left, string right)
60	{
61		int x, y;
62		if(!int.TryParse(left, out x))
63		{
64			return left.CompareTo(right);
65		}
66
67		if(!int.TryParse(right, out y))
68		{
69			return left.CompareTo(right);
70		}
71
72		return x.CompareTo(y);
73	}
74}
Usage
List testItems = new List(new string[]
			                                          	{
			                                          		"z24", "z2", "z15", "z1",
			                                          		"z 21", "z22", "1", "2", "5", "3", "abc1", "abc92", "abc9", "abc9z4",
			                                          		"z3", "z20", "a5", "z11",
			                                          	});
			testItems.Sort(new NaturalComparer());
			foreach(string _item in testItems)
			{
				Console.WriteLine(_item);
			}
Notes
This is loosely based off an implementation by IanG http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting In response to a post by Jeff Atwood http://www.codinghorror.com/blog/archives/001018.html I butchered the code till it's unrecognizable, but I'll still give credit :D I've updated this from the original implementation to be more efficient. The original version would sort 1,000,000 values in about 2 minutes. This version sorts in a little over 6 seconds. It's still 3X as long as the normal sort, but that's close enough for me.