Sorting List<List<string>>

Andrew Harris

I have a List of List which can be of variable but repeated width. For example:

var test = new List<List<string>>();
test.Add(new List<string> {"1","2","3"});
test.Add(new List<string> {"1","4","12"});
test.Add(new List<string> {"1","2","9"});
test.Add(new List<string> {"1","4","5"});
test.Add(new List<string> {"6","7","8"});

But it could also be:

var test = new List<List<string>>();
test.Add(new List<string> {"1","2","3","3","3"});
test.Add(new List<string> {"1","4","12","1","7"});
test.Add(new List<string> {"1","2","9","9","4"});
test.Add(new List<string> {"1","4","5","8","5"});
test.Add(new List<string> {"6","7","8","2","7"});

It will never be:

var test = new List<List<string>>();
test.Add(new List<string> {"1"});
test.Add(new List<string> {"1","5"});
test.Add(new List<string> {"1","2","3"});
test.Add(new List<string> {"1","5"});
test.Add(new List<string> {"6","7","8"});

And I would like to have the list ordered left column to right column like:

["1","2","3"];
["1","2","9"];
["1","4","5"];
["1","4","12"];
["6","7","8"];

The following is a little test I setup to see what I could come up with (https://dotnetfiddle.net/B5ljig):

var test = new List<List<string>>();
test.Add(new List<string> {"1","2","3"});
test.Add(new List<string> {"1","4","5"});
test.Add(new List<string> {"1","2","3"});
test.Add(new List<string> {"1","4","5"});
test.Add(new List<string> {"6","7","8"});

var query = test.AsQueryable();
query = query.OrderBy(a=>a[0]);
var max = categories.Select(a=>a.Count()).Max();
for (int i = 1; i < max; i++)
{
    query = query.ThenBy(a=>a[i]); // Error Here
}
var sorted = query.ToList();

Unfortunately the commented line errors with

'IQueryable>' does not contain a definition for 'ThenBy' and no accessible extension method 'ThenBy' accepting a first argument of type 'IQueryable>' could be found (are you missing a using directive or an assembly reference?)

Any ideas? Thoughts? Better ways.

Dmitry Bychenko

If you want to Sort anything using your own rules, you can implement a custom comparer (IComparer<T>), IComparer<IList<string>> in this particular case:

   public class MyListComparer : IComparer<IList<string>> {
      private static int CompareItems(string left, string right) {
        if (left.StartsWith("-"))
          if (right.StartsWith("-"))
            return -CompareItems(left.TrimStart('-'), right.TrimStart('-'));
          else
            return -1;
        else if (right.StartsWith("-"))
          return 1;

        left = left.TrimStart('0');
        right = right.TrimStart('0');  

        int result = left.Length.CompareTo(right.Length);

        if (result != 0)
          return result;

        for (int i = 0; i < left.Length; ++i) {
          result = left[i] - right[i];

          if (result != 0)
            return result;
        }

        return 0;
      }

      public int Compare(IList<string> x, IList<string> y) {
        if (ReferenceEquals(x, y))
          return 0;
        else if (null == x)
          return -1;
        else if (null == y)
          return 1;

        for (int i = 0; i < Math.Min(x.Count, y.Count); ++i) {
          int result = CompareItems(x[i], y[i]);

          if (result != 0)
            return result;
        }

        return x.Count.CompareTo(y.Count);
      }
    }

Then sort:

  var test = new List<List<string>>();

  test.Add(new List<string> { "1", "2", "3" });
  test.Add(new List<string> { "1", "4", "12" });
  test.Add(new List<string> { "1", "2", "9" });
  test.Add(new List<string> { "1", "4", "5" });
  test.Add(new List<string> { "6", "7", "8" });

  // Time to sort with a custom comparer
  test.Sort(new MyListComparer());

  string report = string.Join(Environment.NewLine, test
    .Select(line => string.Join(", ", line)));

  Console.Write(report);

Outcome:

  1, 2, 3
  1, 2, 9
  1, 4, 5
  1, 4, 12
  6, 7, 8

you can use the comparer with Linq query as well:

  var sorted = test.OrderBy(new MyListComparer());

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related