tags:

views:

874

answers:

5

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

+1  A: 

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

_allStatInfo.Sort((x, y) => x.date - y.date);
Cecil Has a Name
Thanks for the answer but I get an error: Cannot convert lambda expression to type System.Collections.Generic.IComparer<AdminTool.app.models.StatInfo>' because it is not a delegate type
marcgg
You need at least C# 3.0 (Visual Studio 2008/any edition).
Cecil Has a Name
+9  A: 

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)));
Ben M
Thanks, the second method worked. I don't use LINQ so I can't test the second one.
marcgg
A: 

For a DateTime there shouldn't be a need to compare.

_allStatInfo.OrderyBy(d => d.date);

or

_allStatInfo.OrderByDescending(d => d.Date);
TruthStands
Both methods return the list back, so you would need _allStatInfo = _allStatInfo.OrderBy(d => d.date).ToList();
TruthStands
Thanks, but a List<> has no such functions if I'm not mistaking
marcgg
I guess this is LINQ. I'm not using LINQ
marcgg
+1  A: 

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.

Dan Tao
thanks. It does not apply really to my situation since I'll only sort by date in this particular situation, but I'll keep this in mind for later
marcgg
@marcgg: The code in my answer makes sorting by date the default behavior. So if you are only sorting by date, I think that is exactly what you want.
Dan Tao
+4  A: 

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));
    }
}
Jon Skeet
Are you saying my code is ugly? :-(
Ben M
Oh thanks, just when I was saying that I didn't get an answer from you on a C# question :) I'll keep Ben's answer accepted but I upvoted yours and I'm sure it will be right below
marcgg
@Ben: I just don't like that many brackets if I can help it :)
Jon Skeet