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.
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.
Comments