Unknown Coder
Unknown Coder

Reputation: 6731

C# list sort by two columns

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

Answers (7)

sayed saad
sayed saad

Reputation: 672

Comparison Chain in C#

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

John F. Doran
John F. Doran

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

Geir Sagberg
Geir Sagberg

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

jocull
jocull

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

lahsrah
lahsrah

Reputation: 9173

var sortResult = result.OrderBy(a => a.CheckedIn).ThenBy(a => a.LastName).ToList();

Upvotes: 23

Serge Wautier
Serge Wautier

Reputation: 21878

result.Sort((x,y) => x.CheckedIn==y.CheckedIn ? 
  string.Compare(x.LastName, y.LastName) : 
  (x.CheckedIn ? -1 : 1) );

Upvotes: 27

Tarang
Tarang

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

Related Questions