Sisyphus
Sisyphus

Reputation: 708

Sort List of strings as numbers - found solution but don't know how to implement

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

Answers (2)

Guffa
Guffa

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

manojlds
manojlds

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

Related Questions