通用列表FindAll()与foreach

时间:2009-03-23 18:25:55

标签: c# .net generics

我正在查看通用列表,以根据某个参数查找项目。

总的来说,最好和最快的实施是什么? 1.循环遍历列表中的每个项目并将每个匹配保存到新列表并返回

foreach(string s in list)
{ 
    if(s == "match")
    {
       newList.Add(s);
    }
} 

return newList;

或者
2.使用FindAll方法并向其传递委托。

newList = list.FindAll(delegate(string s){return s == "match";});

难道它们都不是在~O(N)中运行?这里最好的做法是什么?

此致 乔纳森

8 个答案:

答案 0 :(得分:46)

您绝对应该使用FindAll方法或等效的LINQ方法。另外,如果可以,请考虑使用更简洁的lambda而不是您的委托(需要C#3.0):

var list = new List<string>();
var newList = list.FindAll(s => s.Equals("match"));

答案 1 :(得分:9)

在这种情况下,我会使用FindAll method,因为它更简洁,而且IMO更易于阅读。

你是对的,他们几乎都会在O(N)时间内执行,虽然foreach statement 不必执行委托调用(委托会产生轻微的开销,而不是直接调用方法)。

我必须强调这种差异是多么微不足道,除非你在大量列表上进行大量操作,否则它很可能永远不会有所作为

与往常一样,测试瓶颈在哪里并采取相应的行动。

答案 2 :(得分:5)

乔纳森,

您可以在Linq To Action的第5章(性能考虑因素)中找到一个很好的答案。

他们为每次执行大约50次的搜索测量a,并且每个周期得出foreach = 68ms / List.FindAll =每个周期62ms。真的,你可能只想创建一个测试并亲自看看。

答案 3 :(得分:4)

List.FindAll为O(n),将搜索整个列表。

如果你想用foreach运行你自己的迭代器,我建议使用yield语句,如果可能的话返回一个IEnumerable。这样,如果你最终只需要你收藏的一个元素,它会更快(因为你可以停止你的调用者而不会耗尽整个集合)。

否则,请坚持使用BCL界面。

答案 4 :(得分:3)

任何表演差异都会非常小。我建议FindAll是为了清晰,或者,如果可能的话,我建议使用Enumerable.Where。我更喜欢使用Enumerable方法,因为它允许重构代码的更大灵活性(你不依赖于List<T>)。

答案 5 :(得分:2)

是的,他们两个实现都是O(n)。他们需要查看列表中的每个元素以查找所有匹配项。在可读性方面,我也更喜欢FindAll。出于性能考虑,请查看LINQ in Action(第5.3节)。如果您使用的是C#3.0,则还可以应用lambda表达式。但这只是锦上添花:

var newList = aList.FindAll(s => s == "match");

答案 6 :(得分:1)

我和Lambdas

List<String> newList = list.FindAll(s => s.Equals("match"));

答案 7 :(得分:0)

除非C#团队改进了LINQFindAll的效果,否则以下文章似乎表明forforeach将胜过LINQ和对象枚举FindAllLINQ on Objects Performance

这个艺术可以追溯到2009年3月,就在这篇帖子最初提出之前。