Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort a list of objects by a specific field in C#?

Tags:

c#

sorting

I have this class:

public class StatInfo
{
  public string contact;
  public DateTime date;
  public string action;
}

then I have a list of StatInfo, but I'm not sure how to sort it according to the date field. Should I use the sort method? Should I create my own?

var _allStatInfo = new List<StatInfo>();
// adding lots of stuff in it
_allStatInfo.SortByDate???

What is the best way of doing this without having to write tons of code (if possible)?

Thanks

like image 652
marcgg Avatar asked Aug 19 '09 18:08

marcgg


People also ask

How can we sort a list of objects?

sort() method to sort a list of objects using some examples. By default, the sort() method sorts a given list into ascending order (or natural order). We can use Collections. reverseOrder() method, which returns a Comparator, for reverse sorting.

Can you sort a list C#?

Sorting in C# In C#, we can do sorting using the built-in Sort / OrderBy methods with the Comparison delegate, the IComparer , and IComparable interfaces.

Can we sort array of objects?

To sort an array of objects, you use the sort() method and provide a comparison function that determines the order of objects.


4 Answers

Using LINQ:

var sortedList = _allStatInfo.OrderBy(si => si.date).ToList();

Sorting the original list:

_allStatInfo.Sort(new Comparison<StatInfo>((x, y) => DateTime.Compare(x.date, y.date)));
like image 100
Ben M Avatar answered Oct 17 '22 11:10

Ben M


I see you've got the answer anyway, but...

  1. You can avoid some ugliness by just splitting the statement into two halves:

    Comparison<StatInfo> comparison = (x, y) => DateTime.Compare(x.date, y.date);
    _allStatInfo.Sort(comparison);
    

    You might want to consider just calling CompareTo directly, too:

    Comparison<StatInfo> comparison = (x, y) => x.date.CompareTo(y.date);
    _allStatInfo.Sort(comparison);
    
  2. You could create an IComparer<T> implementation using my ProjectionComparer class - it's part of MiscUtil, and I've included an uncommented version at the bottom of this answer. You'd then write:

    _allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => x.date));
    
  3. Even if you're using .NET 2.0, you can still use LINQ by way of LINQBridge.

Here's the ProjectionComparer class required for the second answer. The first couple of classes are really just helpers to let generic type inference work better.

public static class ProjectionComparer
{
    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey>
        (Func<TSource, TKey> projection)
    {
        return new ProjectionComparer<TSource, TKey>(projection);
    }

    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey>
        (TSource ignored, Func<TSource, TKey> projection)
    {
        return new ProjectionComparer<TSource, TKey>(projection);
    }

}

public static class ProjectionComparer<TSource>
{
    public static ProjectionComparer<TSource, TKey> Create<TKey>
        (Func<TSource, TKey> projection)
    {
        return new ProjectionComparer<TSource, TKey>(projection);
    }
}

public class ProjectionComparer<TSource, TKey> : IComparer<TSource>
{
    readonly Func<TSource, TKey> projection;
    readonly IComparer<TKey> comparer;

    public ProjectionComparer(Func<TSource, TKey> projection)
        : this (projection, null)
    {
    }

    public ProjectionComparer(Func<TSource, TKey> projection,
                              IComparer<TKey> comparer)
    {
        projection.ThrowIfNull("projection");
        this.comparer = comparer ?? Comparer<TKey>.Default;
        this.projection = projection;
    }

    public int Compare(TSource x, TSource y)
    {
        // Don't want to project from nullity
        if (x==null && y==null)
        {
            return 0;
        }
        if (x==null)
        {
            return -1;
        }
        if (y==null)
        {
            return 1;
        }
        return comparer.Compare(projection(x), projection(y));
    }
}
like image 32
Jon Skeet Avatar answered Oct 17 '22 11:10

Jon Skeet


To illustrate Robert C. Cartaino's answer:

public class StatInfo : IComparable<StatInfo>
{
    public string contact;
    public DateTime date;
    public string action;

    public int CompareTo(StatInfo value)
    {
        return this.date.CompareTo(value.date);
    }
}

var _allStatInfo = new List<StatInfo>();

// this now sorts by date
_allStatInfo.Sort();

Not the most general solution but good if you're only going to sort by date. And, as Robert said, you can still always override the default sort by passing an IComparer parameter to the sort method.

like image 5
Dan Tao Avatar answered Oct 17 '22 11:10

Dan Tao


Use a lambda expression to map a pair to a comparison:

_allStatInfo.Sort((x, y) => x.date - y.date);
like image 4
Cecil Has a Name Avatar answered Oct 17 '22 12:10

Cecil Has a Name