2010-03-22 66 views
8

我有3 (Edit)互斥 IEnumerables我想迭代。我想要做这样的事情:forea覆盖IEnumerable的集合

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

有没有一种更简洁的方式来做到这一点:

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

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

... 

我能想到的是最好的方法?看起来像组合IEnumberables应该是微不足道的。

回答

20

使用LINQ:

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

有关信息,UnionConcat之间这里的区别是,Union会做额外的工作来保证唯一性;所以如果你不期望重复(或者:不介意他们),那么Concat是更快。

+2

呃......我从Concat开始,然后去了Union,然后决定我无法决定使用哪个,所以我删除了我的答案。无论如何,我喜欢你的解释差异。 +1 – Randolpho 2010-03-22 20:54:55

+0

正是我在找的东西。谢谢! – sdr 2010-03-22 20:57:56

+0

@sdr:请注意,这里存在时间/空间折衷。假设你没有三个而是二十个这样的列表,每个列表都有一万个元素。您的方法(将它们连接在一起形成一个大列表)需要大约20 x 10K额外引用,并需要20 x 10K参考复制操作。另一方面,20个天真连接占用零个额外引用,但嵌套连接的复制负担基于它们的嵌套深度,因此将会有10 x 11 x 10K = 110K份,而不是20K份。有关详细信息,请参阅http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx。 – 2010-03-22 22:42:49

0

使用LINQ Union方法。

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

如果您绝对需要在一个循环中完成此操作,我会使用LINQ。 – 2010-03-22 20:52:51

+0

没有想到这一点。但是,这不会因为需要将它们全部进行比较而展望吗?特别是因为这三个团体是相互排斥的。 – sdr 2010-03-22 20:53:52

+1

有关信息,'Union'在这里会比'Concat'更加昂贵,并且很可能会对'AddRange'方法产生不同的结果(本质上是一个'Concat')。 – 2010-03-22 20:53:54

0

是否有理由需要在一个循环中完成它?如果是这样,第二种方式可能是最好的。没有什么会像第一种方式那样工作。

除非在一个循环中有一个压倒一切的需要,否则我会在三个循环中执行,这样会更省时。

+1

我认为“更省时”是一个很大的主张。还要注意的是,创建一个列表(分配,复制等)也有开销。而且非常多的东西*会像第一种方式一样工作。 – 2010-03-22 20:57:32

+0

@Scott,如果他以同样的方式与每辆车一起工作,为什么他会想要多个循环?这只是多余的代码。 – 2010-03-22 20:59:07

3

正如在其他答案中指出的,联盟做了额外的工作以消除重复,Concat只是简单地连接序列。但是,正如我在上面的评论中指出的那样,深嵌套concats存在性能成本。您也可以考虑使用到的SelectMany压扁了一堆迭代器:

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

你可能会觉得这是你应该发现你确实有这样三个以上的列表进行迭代更加灵活。