获取 IEnumerable<T> 计数的最佳方法
Posted
技术标签:
【中文标题】获取 IEnumerable<T> 计数的最佳方法【英文标题】:The best way to get a count of IEnumerable<T> 【发布时间】:2010-09-06 22:11:03 【问题描述】:在不枚举集合中的所有项目的情况下获取 IEnumerable 集合中的项目计数的最佳/最简单方法是什么?
可以使用 LINQ 或 Lambda 吗?
【问题讨论】:
Howto: Count the items from a IEnumerable<T> without iterating?的可能重复 【参考方案1】:在任何情况下,您都必须遍历它。 Linq 提供了Count
方法:
var result = myenum.Count();
【讨论】:
是的,只要你有“使用 System.Linq;”就可以了在文件的开头。没有 Linq,这是行不通的。【参考方案2】:解决方案取决于您不想枚举集合的原因。
如果是因为枚举集合可能很慢,那么没有更快的解决方案。如果可能,您可能要考虑使用 ICollection。除非枚举非常慢(例如它从磁盘读取项目),否则速度应该不是问题。
如果是因为枚举集合需要更多代码,那么它已经以 .Count() 扩展方法的形式为您编写好了。只需使用 MyEnumerable.Count()。
如果是因为您希望在计数后能够枚举集合,那么 .Count() 扩展方法允许这样做。您甚至可以在您正在枚举的集合上调用 .Count() ,它将从计数之前的位置继续。例如:
foreach (int item in Series.Generate(5))
Console.WriteLine(item + "(" + myEnumerable.Count() + ")");
会给出结果
0 (5)
1 (5)
2 (5)
3 (5)
4 (5)
如果是因为枚举具有副作用(例如,写入磁盘/控制台)或依赖于可能在计数和枚举之间发生变化的变量(例如,从磁盘读取)[N.B.如果可能的话,我建议重新考虑架构,因为这会导致很多问题] 然后考虑的一种可能性是将枚举读入间歇性存储。例如:
List<int> seriesAsList = Series.Generate(5).ToList();
以上所有内容都假设您无法更改类型(即它是从您不拥有的库中返回的)。如果可能,您可能需要考虑更改为使用具有 Count 属性的 ICollection 或 IList(ICollection 的范围比 IList 更广泛)。
【讨论】:
【参考方案3】:您必须枚举才能获得计数。其他结构(如 List)保持运行计数。
【讨论】:
如果将 IEnumerable 变量传递给方法,那么 variable.Count() 对我有用。 @Vikram 据我所知,这不可能。你确定你没有在某个地方投射? 对于 IEnumerable使用这个。
IEnumerable list =..........;
list.OfType<T>().Count()
它将返回计数。
【讨论】:
将名称list
命名为 IEnumerable
至少可以说是令人困惑。【参考方案5】:
还有 IList 或 ICollection,如果您想使用仍然有些灵活但也具有您需要的功能的构造。它们都暗示 IEnumerable。
【讨论】:
【参考方案6】:这也取决于您想通过计数来实现什么。如果您有兴趣查找可枚举集合是否有任何元素,您可以使用
myEnumerable.Any() over myEnumerable.Count() 前者将产生第一个元素,后者将产生所有元素。
【讨论】:
【参考方案7】:IEnumerable 必须遍历每个项目。得到完整的计数。 如果您只需要检查 IEnumerable 中是否有一个或多个项目,一种更有效的方法是检查是否有任何项目。 Any() 仅检查是否有值,不会遍历所有内容。
IEnumerable myStrings = new List()"one","two", "three";
bool hasValues = myStrings.Any();
【讨论】:
【参考方案8】:无法使用 LINQ,因为调用 .Count(...) 确实会枚举集合。如果您遇到无法遍历集合两次的问题,请尝试以下操作:
List<MyTableItem> myList = dataContext.MyTable.ToList();
int myTableCount = myList.Count;
foreach (MyTableItem in myList)
...
【讨论】:
【参考方案9】:如果您需要计数然后循环,则最好使用列表。
如果您使用 count 来检查成员,您可以使用 Any()
来避免枚举整个集合。
【讨论】:
【参考方案10】:最好的解决方案 - 我认为是执行以下操作:
-
使用 System.Linq.Dynamic;
myEnumerable.AsQueryable().Count()
【讨论】:
错了。这并不比其他任何事情都好,而且可能更糟。 还是一样.. 如果我们只需要 Count 怎么办,因为我们不想迭代每条记录.. 为什么?因为我们想要快..【参考方案11】:当我想使用 Count 属性时,我使用实现 IEnumerable 和 ICollection 接口的 ILIST。 ILIST 数据结构是一个数组。我逐步使用 VS 调试器,发现下面的 .Count 属性返回 Array.Length 属性。
IList<string> FileServerVideos = Directory.GetFiles(VIDEOSERVERPATH, "*.mp4");
if (FileServerVideos.Count == 0)
return;
【讨论】:
以上是关于获取 IEnumerable<T> 计数的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
无法将类型“IEnumerable<T>”隐式转换为“ActionResult<IEnumerable<T>>”
在 C# 中将多个 IEnumerable<T> 提要混合为一个
将生成 IEnumerable<T> 的 TransformBlock 链接到接收 T 的块
将 IEnumerable<Ienumerable<T>> 转换为 Dictionary<key,IEnumerable<T>>
如何将两个 IEnumerable<T> 连接成一个新的 IEnumerable<T>?
如何将多个 IEnumerable<IEnumerable<T>> 列表添加到 IEnumerable<List<int>>