Reputation: 708
I would like to implement http://www.davekoelle.com/alphanum.html in my code to do some natural sorting of strings with numbers at beginning and end. My problem, having not done much sorting is how do I implement this into my object structure.
I have a
List<string[]> myStringArrays = new List<string[]>();
and I've added 1000's of arrays of this type:
"text", "text", "1, label:3", "","","", etc ...
"text", "text", "2, label:2", "","","", etc ...
"text", "text", "2, label:1", "","","", etc ...
"text", "text", "10, label:3", "","","", etc ...
EDIT: (label is always "label" in this example)
and I've been sorting with LINQ
myStringArrays = myStringArrays.OrderBy(m => m[2]).ToList();
but as you've guessed, it sorts to give the alpha sort "1...", "10..." and so on.
I tried this approach:
myStringArrays = myStringArrays.OrderBy(m => (m[2].Split(',')[0])).ThenBy(m => m[2].Split(':')[2]).ToList();
which works but fails if my 3rd string doesn't meet that specific format. This leads me (eventually) to my question - how would I implement the Alphanum.cs to solve this problem?
Upvotes: 1
Views: 277
Reputation: 700342
It's not hard to implement, it's just a matter of parsing the strings to split them up in numeric and non-numeric characters, and compare them. Here is an implementation that I threw together:
public class AlphaNum : IComparable<AlphaNum> {
private List<string> _alphas;
private List<int> _nums;
public AlphaNum(string value) {
_alphas = new List<string>();
_nums = new List<int>();
bool alpha = true;
int ofs = 0;
for (int i = 0; i <= value.Length; i++) {
if (i == value.Length || Char.IsDigit(value[i]) == alpha) {
string s = value.Substring(ofs, i - ofs);
if (alpha) {
_alphas.Add(s);
} else {
_nums.Add(Int32.Parse(s));
}
ofs = i;
alpha = !alpha;
}
}
}
public int CompareTo(AlphaNum other) {
for (int i = 0;; i++) {
bool e = i >= _alphas.Count;
bool oe = i >= other._alphas.Count;
if (e || oe) return e && oe ? 0 : e ? -1 : 1;
int c = _alphas[i].CompareTo(other._alphas[i]);
if (c != 0) return c;
e = i >= _nums.Count;
oe = i >= other._nums.Count;
if (e || oe) return e && oe ? 0 : e ? -1 : 1;
c = _nums[i].CompareTo(other._nums[i]);
if (c != 0) return c;
}
}
}
Usage:
myStringArrays = myStringArrays.OrderBy(x => new AlphaNum(x[2])).ToList();
Upvotes: 1
Reputation: 301147
This implementation of natural sort should get you started: http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting
Upvotes: 0