Anthbs
Anthbs

Reputation: 184

C# Linq query to find invalid entries

I'm trying do some manual validation for data in a List.

I have a MachineryRecord class which I sort then group by the JobNumber, now I need to find any results in each of the grouped lists that have overlapping times eg. Start time to End time overlaps another records StartTime to EndTime.

So far this is what I have got:

int invalidCount = 0;
var sorted = _machineRecords.OrderBy(x => x.StartTime).ToList();
var grouped = sorted.GroupBy(x => x.JobNumber).ToList();
foreach(IGrouping<int,MachineryRecord> mac in grouped)     
{
   var queryResults = mac.//Linq query to find overlapping times
   invalidCount += queryResults.Count;
}
if(invalidCount > 0)
    return false;
else
    return true;

and heres a cutdown version of MachineRecord object:

public class MachineryRecord
{
    public int ID { get; set; }
    public float StartTime { get; set; }
    public float EndTime { get; set; }
}

So my question is what is the linq query to achieve this?

Thanks for the help.

Upvotes: 2

Views: 293

Answers (2)

Zar Shardan
Zar Shardan

Reputation: 5921

This is a non-LINQ version that would use the fact the collection is sorted by start date:

    List<Tuple<MachineryRecord,MachineryRecord>> OverlapingRecords(IEnumerable<MachineryRecord> sortedRecords)
    {
        var result = new List<Tuple<MachineryRecord, MachineryRecord>>();
        MachineryRecord prev = null;
        foreach (var current in sortedRecords)
        {
            if (prev != null)
            {
                if (current.StartTime < prev.EndTime) { result.Add(new Tuple<MachineryRecord, MachineryRecord>(prev,current)); }
            }
            prev = current;
        }
        return result;
    }

I haven't tested it though ;)

Upvotes: 0

Daniel Br&#252;ckner
Daniel Br&#252;ckner

Reputation: 59675

Two intervals a and b overlap if a.StartTime < b.EndTime and a.EndTime > b.StartTime assuming the start time is always before the end time. Therefore this can be expressed as follows.

var invalidCount = _machineRecords.Count(a =>
                       _machineRecords.Any(b =>
                           (a.ID != b.ID) &&
                           (a.JobNumber == b.JobNumber) &&
                           (a.StartTime < b.EndTime) &&
                           (a.EndTime > b.StartTime)));

Including the final check of invalidCount this can be simplified to a single return statement.

return !_machineRecords.Any(a =>
           _machineRecords.Any(b =>
               (a.ID != b.ID) &&
               (a.JobNumber == b.JobNumber) &&
               (a.StartTime < b.EndTime) &&
               (a.EndTime > b.StartTime)));

Upvotes: 3

Related Questions