Foreach над коллекцией IEnumerables - PullRequest
8 голосов
/ 22 марта 2010

У меня есть 3 (Edit) взаимоисключающие IEnumerables, которые я хочу перебрать. Я хочу сделать что-то вроде этого:

IEnumerable<Car> redCars = GetRedCars();
IEnumerable<Car> greenCars = GetGreenCars();
IEnumerable<Car> blueCars = GetBlueCars();

foreach(Car c in (redCars + greenCars + blueCars)) {
    c.DoSomething();
}

...

Лучший способ, о котором я могу думать, это:

...
List<Car> allCars = new List();
allCars.AddRange(redCars);
allCars.AddRange(greenCars);
allCars.AddRange(blueCars);
foreach(car in allCars) {
    ...
}
...

Есть ли более лаконичный способ сделать это? Похоже, объединение IEnumberables должно быть тривиальным.

Ответы [ 4 ]

20 голосов
/ 22 марта 2010

С LINQ:

foreach(car in redCars.Concat(greenCars).Concat(blueCars)) {
    //...
}

Для информации, разница между Union и Concat в том, что Union сделает дополнительную работу, чтобы гарантировать уникальность; так что если вы не ожидаете дубликатов (или, наоборот, не обращайте на них внимания), тогда Concat быстрее.

3 голосов
/ 23 марта 2010

Как отмечалось в других ответах, Union выполняет дополнительную работу по удалению дубликатов, Concat просто объединяет последовательности.Однако, как я уже отмечал в комментарии выше, производительность глубоко вложенных конкатов снижается.Вы можете также рассмотреть возможность использования SelectMany, чтобы сгладить группу итераторов:

var carLists = new[]{GetRedCars(), GetGreenCars(), GetBlueCars()};
var allCars = from carList in carLists
              from car in carList 
              select car;
foreach(var c in allCars) { ... }

Возможно, вы обнаружите, что это более гибко, если вы обнаружите, что на самом деле у вас есть более трех списков для итерации.

0 голосов
/ 22 марта 2010

Есть ли причина, по которой вам нужно сделать это за один цикл? Если это так, второй способ, вероятно, является лучшим. Там нет ничего, что будет работать, как в первом случае.

Если нет первостепенной необходимости делать это за один цикл, я бы сделал это за три цикла, что было бы более эффективным по времени.

0 голосов
/ 22 марта 2010

Используйте метод LINQ Union.

foreach(Car c in redCars.Union(greenCars).Union(blueCars))
{
    c.DoSomething();
}
...