Reputation: 6731
I have a C# custom object list that I need to sort by two different variables one is a boolean and the other is a string. I can sort by either of the criteria, but I'm having trouble figuring out how to combine them. The sort should be all of the boolean values first (CheckedIn) and then the last name for each of the values. Right now I use
result.Sort((x, y) => string.Compare(x.CheckedIn.ToString(), y.CheckedIn.ToString()));
result.Sort((x, y) => string.Compare(x.LastName, y.LastName));
But how can I combine then so that my results are like
CheckedIn-Name
No - Aames
No - Smith
Yes - Barnes
Yes - Peters
Upvotes: 23
Views: 56951
Reputation: 672
Here's my comparison chain solution. It will take care of aggregating all comparer classes you are interested in sorting by. the builder pattern makes it easy to provide columns to sort by and get a sorted list in return.
Upvotes: 0
Reputation: 1
I was able to do something fast/dirty by doing this.. since both columns are text, just add them together to sort in one quick pass.
this.Project.Tasks.Sort((x, y) => String.Compare((x.Assignee + x.Task), (y.Assignee + y.Task)));
Upvotes: 0
Reputation: 9821
Here is an extension method I wrote for sorting a list by any number of keys:
public static class ListExtensions
{
public static void SortBy<T>(this List<T> list, params Expression<Func<T, IComparable>>[] keys)
{
if (list == null)
throw new ArgumentNullException("list");
if(keys == null || !keys.Any())
throw new ArgumentException("Must have at least one key!");
list.Sort((x, y) => (from selector in keys
let xVal = selector.Compile()(x)
let yVal = selector.Compile()(y)
select xVal.CompareTo(yVal))
.FirstOrDefault(compared => compared != 0));
}
}
Usage:
var List<Person> persons = GetPersons();
myList.SortBy(p => p.LastName, p => p.FirstName);
Note that this is roughly equivalent to: myList = myList.OrderBy(p => p.LastName).ThenBy(p => p.FirstName)
.
Upvotes: 1
Reputation: 21095
I have a class that creates CSV files using List<List<string>>
in a _Records
variable. I needed way to sort it after the fact, and LINQ was no good.
This is what I created as a multi-sort by passing in the indexes of the columns I wanted to sort.
public void OrderBy(params int[] columnIndexes)
{
_Records.Sort((x, y) =>
{
foreach (int i in columnIndexes)
{
int result = string.Compare(x[i], y[i]);
if (result != 0)
return result;
}
return 0;
});
}
Usage would then be...
csv.OrderBy(1, 3, 5);
Upvotes: 3
Reputation: 9173
var sortResult = result.OrderBy(a => a.CheckedIn).ThenBy(a => a.LastName).ToList();
Upvotes: 23
Reputation: 21878
result.Sort((x,y) => x.CheckedIn==y.CheckedIn ?
string.Compare(x.LastName, y.LastName) :
(x.CheckedIn ? -1 : 1) );
Upvotes: 27
Reputation: 656
use linq.
if you have list L of objects of class
public class temp
{
public bool x;
public string y;
}
then use:
L.orderby(a=>a.x).thenby(a=>a.y);
you can chain it as far as you like.
Upvotes: 46