Reputation: 184
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
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
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