sdr
sdr

Reputation: 1665

Foreach over a collection of IEnumerables

I have 3 (Edit) mutually exclusive IEnumerables that I want to iterate over. I want to do something like this:

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

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

...

The best way I can think of is:

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

Is there a more concise way to do this? Seems like combinding IEnumberables should be trivial.

Upvotes: 8

Views: 1478

Answers (4)

Eric Lippert
Eric Lippert

Reputation: 660058

As noted in other answers, Union does extra work to eliminate duplicates, Concat simply concatenates the sequences. However, as I noted in a comment above, there are performance costs to deeply nested concats. You might consider also using a SelectMany to flatten a bunch of iterators:

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

You might find that to be more flexible should you discover that you actually have way more than three lists to iterate.

Upvotes: 3

Scott J
Scott J

Reputation: 1331

Is there a reason you need to do it in one loop? If so, the second way is probably the best. There's nothing that will work like the first way.

Unless there's an overriding need to do it in one loop, I'd do it in three loops which would be more time efficient.

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062780

With LINQ:

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

For info, the difference here between Union and Concat is that Union will do extra work to guarantee uniqueness; so if you don't expect duplicates (or alternatively: don't mind them) then Concat is faster.

Upvotes: 20

Elisha
Elisha

Reputation: 23770

Use LINQ Union method.

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

Upvotes: 0

Related Questions