Not a very efficient, but simple comparison algorithm that first separates numbers from non-numbers, then sorts between them will work - see the code below. The drawback comes from the fact that we will make a string for double conversion several times, so you can pre-process numbers (i.e., save their double values in List<double?> ), And then use them instead of always parsing them.
public class StackOverflow_9231493 { public static void Test() { List<string> list = new List<string> { "cat", "4", "5.4", "dog", "-400", "aardvark", "12.23.34.54", "i am a sentence", "0" , }; list.Sort(new Comparison<string>(delegate(string s1, string s2) { double d1, d2; bool isNumber1, isNumber2; isNumber1 = double.TryParse(s1, out d1); isNumber2 = double.TryParse(s2, out d2); if (isNumber1 != isNumber2) { return isNumber2 ? -1 : 1; } else if (!isNumber1) { return s1.CompareTo(s2); } else { return Math.Sign(d1 - d2); } })); Console.WriteLine(string.Join("\n", list)); } }
Comment Based Update :
If you only want to return something without using the comparison directly, you can use the same logic, but wrap the values in a type that knows how to perform the comparison, as shown below.
public class StackOverflow_9231493 { public class Wrapper : IComparable<Wrapper> { internal string value; private double? dbl; public Wrapper(string value) { if (value == null) throw new ArgumentNullException("value"); this.value = value; double temp; if (double.TryParse(value, out temp)) { dbl = temp; } } public int CompareTo(Wrapper other) { if (other == null) return -1; if (this.dbl.HasValue != other.dbl.HasValue) { return other.dbl.HasValue ? -1 : 1; } else if (!this.dbl.HasValue) { return this.value.CompareTo(other.value); } else { return Math.Sign(this.dbl.Value - other.dbl.Value); } } } public static void Test() { List<string> list = new List<string> { "cat", "4", "5.4", "dog", "-400", "aardvark", "12.23.34.54", "i am a sentence", "0" , }; List<Wrapper> list2 = list.Select(x => new Wrapper(x)).ToList(); list2.Sort(); Console.WriteLine(string.Join("\n", list2.Select(w => w.value))); } }