【问题标题】:C# Linq query to find invalid entriesC# Linq 查询以查找无效条目
【发布时间】:2012-12-13 12:57:17
【问题描述】:

我正在尝试对列表中的数据进行一些手动验证。

我有一个 MachineryRecord 类,我对它进行排序,然后按 JobNumber 分组,现在我需要在每个具有重叠时间的分组列表中找到任何结果,例如。开始时间到结束时间与另一个记录 StartTime 到 EndTime 重叠。

到目前为止,这是我得到的:

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;

这是 MachineRecord 对象的缩减版:

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

所以我的问题是实现此目的的 linq 查询是什么?

感谢您的帮助。

【问题讨论】:

  • 时间的格式是什么?你为什么使用浮动?是 24 小时制的吗?你能展示开始和结束时间的样本吗?
  • 抱歉忘了说 StartTime 和 EndTime 取自机器中的计数器,类似于汽车中的里程表,但计算使用的小时数。因此使用浮点数

标签: c# linq validation


【解决方案1】:

假设开始时间总是在结束时间之前,如果a.StartTime &lt; b.EndTimea.EndTime &gt; b.StartTime 两个时间间隔ab 重叠。因此可以表示如下。

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

包括invalidCount 的最终检查,这可以简化为单个返回语句。

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

【讨论】:

  • 这有一个小错误,当检查相同的 MachineRecord 时它返回 true。我将如何修改它来解决这个问题?
  • 已经修复 - 只需比较 ID 或引用 a != b
  • 很好,但它没有利用集合已排序的事实(我假设按开始日期?)
  • 我不认为记录是按开始时间排序的,因为问题中有一个明确的OrderBy。优化该方法并不是那么简单 - 如果有很多违规行为,如果您首先对其进行排序,它可能会减慢整个过程,因为无论如何您都会提前遇到违规行为。如果违规情况很少见,那么对数据进行预分类可能会有所帮助。同样按照问题中的工作编号对数据进行分组似乎是个好主意。但我决定采用一个相对简单的解决方案 - 如果存在性能问题,了解实际数据很容易进行调整。
【解决方案2】:

这是一个非 LINQ 版本,它使用集合按开始日期排序的事实:

    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;
    }

不过我还没有测试过;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多