Преобразование вложенных циклов в один оператор 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]);
}
}
}
}
Ответы
Ответ 1
Вложенные циклы обычно заканчиваются несколькими предложениями "от" (которые преобразуются в вызовы 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();
Обратите внимание, что я использовал перегруженную строку для строки, поскольку мне ее легче читать, чем вызов метода Equals
. Либо все будет работать.
Ответ 2
Попробуйте следующее:
EventLog[] logs = EventLog.GetEventLogs();
remoteAccessLogs.AddRange(
logs.Where(l => l.LogDisplayName.Equals("AAA"))
.Select(l => l.Entries)
.Where(le => le.Source.Equals("BBB"));
Однако, если производительность является проблемой, я бы ожидал, что это будет по крайней мере такой же алгоритмической сложностью, если не хуже, поскольку мы снова повторяем список в AddRange.
Ответ 3
Попробуйте следующее:
from log in logs
where log.LogDisplayName.Equals("AAA")
select
(from entry in log.Entries
where entry.Source.Equals("BBB")
select entry);
Ответ 4
У меня есть это решение, и я предполагаю, что remoteAccessLogs имеет тип List
remoteAccessLogs.AddRange(
from log in EventLog.GetEventLogs()
from entry in log.Entries.Cast<EventLogEntry>()
select entry
);
Изменить
Я забыл о предложениях
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
);
Ответ 5
Посмотрите:
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);
});
});