c# 在 LINQ 查询返回的列表中查找项目并将其值与列表中的另一个项目进行比较

Posted

技术标签:

【中文标题】c# 在 LINQ 查询返回的列表中查找项目并将其值与列表中的另一个项目进行比较【英文标题】:c# find item in list returned by LINQ query and compare its value with another item in list 【发布时间】:2019-04-15 12:20:41 【问题描述】:

我有一个在某一天 (d) 从 LINQ 查询返回的事件列表。

var findJSE = from a in db.DailyGPSTables 
    where (a.EventType == "JE" || a.EventType == "JS") && 
    a.EventDateTime.Value.Day == d.Day select a;

我想比较每组匹配的 JS 和 JE 的时间,看看它们的顺序是否正确,例如。 JS(工作开始)在 JE(工作结束)之前。如果只有一个JS和一个JE,我可以通过使用这个来完成。

foreach (DailyGPSTable e in itCompareDay)

  if (e.EventType == "JE" && e.EventDateTime.Value.Day == d.Day)
   
     var findJS = from a in db.DailyGPSTables where a.EventType == "JS" && a.EventDateTime.Value.Day == d.Day select a;
     var time = findJS.FirstOrDefault();
     js = time.EventDateTime.Value;
      if (js > e.EventDateTime.Value)
       
         EOOmessage = " On " + e.EventDateTime.Value.ToShortDateString() + " JE before JS";
         errorList.Add(EOOmessage);
         errorListRow.Add(dc);
       
   

但是,如果一天中有多个 JS 是允许的,我会遇到一些麻烦。 @NetMage 为我提供了一个极好的潜在修复,但没有时间尝试正确实施它。我最近的尝试在这里:

//Response.Write("<br>3rd Condition number of JE and JS on " + e.EventDateTime.Value.Day + " match now we see if there is more than one js");
if (findJS.Count() > 1)

    //Response.Write("<br>3.1 Condition there is more than one JS on " + e.EventDateTime.Value.Day + " get time of first js tag find the time of the first je tag");
    var jsTime = findJS.ToList();
    var jeTime = findJE.ToList();

    for (int j = 0; j <= jsTime.Count - 1; j++)
    
        //Response.Write("<br><br>The " + j + " " + jsTime[j].EventType + " Starts on " + jsTime[j].EventDateTime + "<br>");
        var jsTimefor = jsTime[j].EventDateTime;
        for (int k = 0; k <= jeTime.Count - 1; k++)
        
            //Response.Write("<br><br>The " + k + " " + jeTime[k].EventType + " Starts on " + jeTime[k].EventDateTime + "<br>");
            var jeTimefor = jeTime[k].EventDateTime;
            if (jeTime[k].EventDateTime < jsTime[j].EventDateTime)
            
                //Response.Write(" The " + k + " " + jeTime[k].EventType + " Starts on " + jeTime[k].EventDateTime + " and < " + jsTime[j].EventDateTime + " which is " + jsTime[j].EventType + "<br>");
                EOOmessage = " On " + e.EventDateTime.Value.ToShortDateString() + " JE before JS";
                errorList.Add(EOOmessage);
                errorListRow.Add(dc);
            
        
    

此尝试突出显示当天的所有 JE 行,并在没有的情况下创建错误条件。

更新:

我已经能够创建一个包含事件类型和时间的列表。

我将如何遍历该列表并确保第一个事件是 JS 并且它是最早的,下一个事件是 JE 并且按时间顺序是下一个。如果不报错。

我正在努力巩固和循环几天。这个21号只报一个错误,但是23号和27号都有错误。

for (DateTime d = startDate.Date; d <= endDate.Date; d = d.AddDays(1))

    Response.Write("<br>" + d + "<br>");
    var itCompareDay = (from h in db.DailyGPSTables
                        where h.EmplID == EmpID
                                && (h.EventDateTime.Value.Day == d.Day)
                                && (h.EventType == "SS" || h.EventType == "JS" || h.EventType == "LS" || h.EventType == "LE" || h.EventType == "JE" || h.EventType == "SE")
                        orderby h.EventDateTime
                        select h).ToList();
    string EOOmessage="";
    var lastEventType = itCompareDay.Any(x => x.EventType == "JS")? "JE" : "JS";
    foreach (DailyGPSTable e in itCompareDay)
    
        Response.Write("<br>Event Type " + e.EventType + " Count " + dc + " for the " + d.Day + "<br>");
        if (e.EventDateTime.Value.Day == d.Day)
        
            if (e.EventType == lastEventType)
            
                var error = e.EventType == "JS"
                ? "JS before JE"
                : "JE before JS";
                Response.Write("<br>OUT OF SEQUENCE JE" + " ON " + e.EventDateTime.Value.ToShortDateString());
            
            lastEventType = e.EventType;
        
        dc = dc + 1;
    
    rowNumber = rowNumber + dc;

Errors incorrectly reported.

【问题讨论】:

如果一天中有多个 JS 是允许的,我会遇到一些麻烦 - 如果你一天中有多个 JobStart,不能你只拿最新的和 JobEnd 比较一下? @stuartd 不确定我是否关注您,您能否将您的问题放入代码中以便我详细说明? 也许考虑一下您将如何手动执行此操作,使用事件卡列表,其中一些标记为 JS/JE。只穿过甲板一次。如果没有 JS 事件,您的(一对)代码将失败。您无需继续重复基本查询中的day 测试。 @NetMage 请查看更新。 【参考方案1】:

我不确定我是否完全理解这里的设计,在我看来,最好将事件存储在 Event 表中,其中每一行都有一个 StartEnd 列。

但是,如您所述,验证相关项目列表的一种方法是按EventDateTime 对列表进行排序,然后跟踪lastEventType。这样你可以检查当前事件类型是否等于lastEventType,那么它是一个错误。

例如:

public class Event

    public string EventType  get; set; 
    public DateTime? EventDateTime  get; set; 

    public override string ToString()
    
        return $"EventDateTime: EventType";
    


public class Program

    static void Main(string[] args)
                
        // Events for the day ordered by EventDateTime
        var events = new List<Event>
        
            new Event EventType = "JE",
                EventDateTime = DateTime.Parse("10/21/2018 12:23 PM"),
            new Event EventType = "JE",
                EventDateTime = DateTime.Parse("10/21/2018 2:29 PM"),
            new Event EventType = "JE",
                EventDateTime = DateTime.Parse("10/21/2018 2:40 PM"),
            new Event EventType = "JS",
                EventDateTime = DateTime.Parse("10/21/2018 2:15 PM"),
            new Event EventType = "JS",
                EventDateTime = DateTime.Parse("10/21/2018 3:12 AM"),
            new Event EventType = "JS",
                EventDateTime = DateTime.Parse("10/21/2018 12:12 PM"),
        .OrderBy(e => e.EventDateTime);

        // Initialize lastEventType to the opposite of the type of event we 
        // expect to see first (which is "JS" unless there are no "JS" events)
        var lastEventType = events.Any(e => e.EventType == "JS")
            ? "JE" : "JS";

        foreach (var e in events)
        
            var errorMessage = string.Empty;

            // Check for error
            if (e.EventType == lastEventType)
            
                Console.ForegroundColor = ConsoleColor.Red;

                // Create an error message
                var error = e.EventType == "JS"
                    ? "JS before JE"
                    : "JE before JS";

                var dateStr = e.EventDateTime?.ToShortDateString() ?? "[null date]";

                errorMessage = $" - On dateStr this error occurred: [error]";

                // Your code would include:
                // errorList.Add(errorMessage); 
                // errorListRow.Add(dc);
            

            Console.WriteLine(e + errorMessage);
            Console.ResetColor();

            // Update the lastEventType with this event type
            lastEventType = e.EventType;
        

        GetKeyFromUser("\nDone! Press any key to exit...");
    

输出

【讨论】:

感谢您观看鲁弗斯。事件列表必须按输入的时间排序,然后检查以确保它们的顺序正确。 好的,我明白了,数据可能有错误。所以你想按EventDateTime排序,然后验证这些项目是交替的EventType,从JS开始? 我已经用我 认为 你要求的内容更新了答案......你能检查一下吗? 这段代码太显示逻辑了。您可以将设置控制台颜色的代码替换为if (e.EventType == lastEventType) // error logging code here 我更新了示例以更好地展示您如何实现它

以上是关于c# 在 LINQ 查询返回的列表中查找项目并将其值与列表中的另一个项目进行比较的主要内容,如果未能解决你的问题,请参考以下文章

简单介绍C#集合查询Linq在项目中使用详解

将 3 个列表组合成 1 个 LINQ 查询 C#

C# LINQ 在列表中查找重复项

如何在linq C#中使用group by并获取记录列表[重复]

使用 LINQ 根据 C# 中的属性值搜索嵌套在另一个列表中的列表中的项目?

LINQ to XML 查询不返回任何结果