18

I have an array of classes with a property Date, i.e.:

class Record
{
    public DateTime Date { get; private set; }
}

void Summarize(Record[] arr)
{
    foreach (var r in arr)
    {
        // do stuff 
    }
}

I have to find the earliest (minimum) and the latest (maximum) dates in this array.

How can I do that using LINQ?

1
  • 1
    "efficient" and "optimal" need a context. Whould you rather like an algorithm that is efficient in regard to space (memory usage, code size) or time (run time, compile time)? Commented Jan 25, 2010 at 13:51

5 Answers 5

42

If you want to find the earliest or latest Date:

DateTime earliest = arr.Min(record => record.Date);
DateTime latest   = arr.Max(record => record.Date);

Enumerable.Min, Enumerable.Max


If you want to find the record with the earliest or latest Date:

Record earliest = arr.MinBy(record => record.Date);
Record latest   = arr.MaxBy(record => record.Date);

See: How to use LINQ to select object with minimum or maximum property value

Sign up to request clarification or add additional context in comments.

6 Comments

Definitely the most readable way to go. In terms of pure efficiency that wouldn't be the most efficient. I doubt this piece of code would be a bottleneck, though.
@Keith Rousseau: Why makes you think that this wouldn't be the "most efficient"?
@drj: It iterates the array twice. Same complexity, constant factor doubled, though.
@Keith Rousseau et all: Beware of micro optimizations. Only optimize if you know that it is a problem. Side with readability/maintainability until/unless you know it is a problem. In MOST cases, this solution is plenty fine.
@Brian: I'm not saying that you should optimize this piece of code. I was just pointing out that from a pure efficiency standpoint, it is not the most efficient.
|
15

old school solution without LINQ:

DateTime minDate = DateTime.MaxValue;
DateTime maxDate = DateTime.MinValue;
foreach (var r in arr) 
{
    if (minDate > r.Date)
    {
        minDate = r.Date;
    }
    if (maxDate < r.Date)
    {
        maxDate = r.Date;
    }
}

2 Comments

ok, for the downvoter: the original quetion was: with C#, and was edited to with LINQ
In fact, you got confused: (minDate > r.Date) and (maxDate < r.Date). Otherwise minimal and maximum will be swaped.
4

The two in one LINQ query (and one traversal):

arr.Aggregate(
    new { MinDate = DateTime.MaxValue,
          MaxDate = DateTime.MinValue },
    (accDates, record) => 
        new { MinDate = record.Date < accDates.MinDate 
                        ?  record.Date 
                        : accDates.MinDate,
              MaxDate = accDates.MaxDate < record.Date 
                        ?  record.Date 
                        : accDates.MaxDate });

1 Comment

Very interesting! Could you please look at my next question stackoverflow.com/questions/2138391/… I will be happy if you could answer it and I could accept it.
1

Using lambda expressions:

void Summarise(Record[] arr)
{
    if (!(arr == null || arr.Length == 0))
    {
        List<Record> recordList = new List<Record>(arr);
        recordList.Sort((x,y) => { return x.Date.CompareTo(y.Date); });

        // I may have this the wrong way round, but you get the idea.
        DateTime earliest = recordList[0];
        DateTime latest = recordList[recordList.Count];
    }
}

Essentially:

  • Sort into a new list in order of date
  • Select the first and last elements of that list

UPDATE: Thinking about it, I'm not sure that this is the way to do it if you care at all about performance, as sorting the entire list will result in many more comparisons than just scanning for the highest / lowest values.

Comments

1

I'd just make two properties Min,Max, assign them the value of the first item you add to the array, then each time you add a new item just check if its DateTime is less or greater than the Min Max ones.

Its nice and fast and it will be much faster than iterating through the array each time you need to get Min Max.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.