获取 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 变量,它必须是 variable.Count() 或者如果你只是检查是否有任何元素 variable.Any()【参考方案4】:

使用这个。

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>>