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

11

请问能否帮我将这个嵌套结构转换为一个单一的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]);
                    }
                }
            }
        }
5个回答

14

嵌套循环通常最终会有多个“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为空,并且您希望直接迭代它 - 如果想要List<T>,可以调用ToList()。)

这是点符号的形式:

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();

请注意,我使用了字符串的重载==,因为我认为这比调用Equals方法更易于阅读。不过两种方式都可以使用。


我总是忘记可以使用 ==,如http://msdn.microsoft.com/en-us/library/aa664728(VS.71).aspx所述。 - Matt Mitchell
我希望代码示例在iPhone上能够正确显示。这是一个元问题! - Jamie Dixon

0

请尝试以下方法:

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

一个交叉连接会是一个更简单的方法。 - Razor

0

我有一个解决方案,并且我假设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
    );

1
哦,不,他的意思是嵌套的,就像现在这样。 - Shirik

0

看一下:

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

试试这个:

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

然而,如果性能是一个问题,我会预计这至少具有相同的算法复杂度,如果不是更糟,因为我们需要再次迭代列表来添加范围。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接