问题 将嵌套的for循环转换为单个LINQ语句


有人可以帮我把这个嵌套结构变成一个LINQ语句吗?

        EventLog[] logs = EventLog.GetEventLogs();
        for (int i = 0; i < logs.Length; i++)
        {
            if (logs[i].LogDisplayName.Equals("AAA"))
            {
                for (int j = 0; j < logs[i].Entries.Count; j++)
                {
                    if (logs[i].Entries[j].Source.Equals("BBB"))
                    {
                        remoteAccessLogs.Add(logs[i].Entries[j]);
                    }
                }
            }
        }

5707
2017-07-06 05:12


起源



答案:


嵌套循环通常最终会有多个“from”子句(转换为调用 SelectMany 由编译器):

var remoteAccessLogs = from log in EventLogs.GetEventLogs()
                       where log.LogDisplayName == "AAA"
                       from entry in log.Entries
                       where entry.Source == "BBB"
                       select entry;

(那就是假设 remoteAccessLogs 在此调用之前是空的,并且您很乐意直接迭代它 - 您可以调用 ToList() 如果你想要一个 List<T>。)

这是点符号形式:

var remoteAccessLogs = EventLogs.GetEventLogs()
                                .Where(log => log.LogDisplayName == "AAA")
                                .SelectMany(log => log.Entries)
                                .Where(entry => entry.Source == "BBB");

或者列表:

var remoteAccessLogs = EventLogs.GetEventLogs()
                                .Where(log => log.LogDisplayName == "AAA")
                                .SelectMany(log => log.Entries)
                                .Where(entry => entry.Source == "BBB")
                                .ToList();

请注意,我已经使用了重载的== for string,因为我发现它比调用它更容易阅读 Equals 方法。要么会工作。


14
2017-07-06 05:21



我总是忘记使用它是可以接受的 == 按照 msdn.microsoft.com/en-us/library/aa664728(VS.71).aspx - Matt Mitchell
我希望在iPhone上正确显示代码示例。我觉得有一个对我来说! - Jamie Dixon


答案:


嵌套循环通常最终会有多个“from”子句(转换为调用 SelectMany 由编译器):

var remoteAccessLogs = from log in EventLogs.GetEventLogs()
                       where log.LogDisplayName == "AAA"
                       from entry in log.Entries
                       where entry.Source == "BBB"
                       select entry;

(那就是假设 remoteAccessLogs 在此调用之前是空的,并且您很乐意直接迭代它 - 您可以调用 ToList() 如果你想要一个 List<T>。)

这是点符号形式:

var remoteAccessLogs = EventLogs.GetEventLogs()
                                .Where(log => log.LogDisplayName == "AAA")
                                .SelectMany(log => log.Entries)
                                .Where(entry => entry.Source == "BBB");

或者列表:

var remoteAccessLogs = EventLogs.GetEventLogs()
                                .Where(log => log.LogDisplayName == "AAA")
                                .SelectMany(log => log.Entries)
                                .Where(entry => entry.Source == "BBB")
                                .ToList();

请注意,我已经使用了重载的== for string,因为我发现它比调用它更容易阅读 Equals 方法。要么会工作。


14
2017-07-06 05:21



我总是忘记使用它是可以接受的 == 按照 msdn.microsoft.com/en-us/library/aa664728(VS.71).aspx - Matt Mitchell
我希望在iPhone上正确显示代码示例。我觉得有一个对我来说! - Jamie Dixon


尝试这个:

 EventLog[] logs = EventLog.GetEventLogs(); 
 remoteAccessLogs.AddRange(
   logs.Where(l => l.LogDisplayName.Equals("AAA"))
     .Select(l => l.Entries)
     .Where(le => le.Source.Equals("BBB"));

但是,如果性能是一个问题,我预计这至少会有相同的算法复杂性,如果不是更糟,因为我们再次迭代列表到AddRange。


0
2017-07-06 05:15





请尝试以下方法:

from log in logs 
where log.LogDisplayName.Equals("AAA")
select 
   (from entry in log.Entries
    where entry.Source.Equals("BBB")
    select entry);

0
2017-07-06 05:16



交叉连接将是一种更简单的方法 - Vince Panuccio


我有这个解决方案,我假设remoteAccessLogs是List类型

remoteAccessLogs.AddRange(

        from log in EventLog.GetEventLogs()
        from entry in log.Entries.Cast<EventLogEntry>()
        select entry
    );

编辑

我忘记了where子句

List<EventLogEntry> remoteAccessLogs = new List<EventLogEntry>();


    remoteAccessLogs.AddRange(

        from log in EventLog.GetEventLogs()
        where log.LogDisplayName.Equals("AAA")
        from entry in log.Entries.Cast<EventLogEntry>()
        where entry.Source.Equals("BBB")
        select entry
    );

0
2017-07-06 05:20



呃,不,他的意思是嵌套,就像它一样。 - Shirik


看一看:

List<Entries> result = new List<Entries>();

GetEventLogs().Where(x => x.LogDisplayName.Equals("AAA")).ToList().ForEach(delegate(Log en)
{
    en.Entries.Where(y => y.Source.Equals("BBB", StringComparison.InvariantCultureIgnoreCase)).ToList().ForEach(delegate(Entries ent)
    {
        result.Add(ent);
    });
});

0
2017-07-06 06:39