可枚举.跳过和排序
本文关键字:排序 枚举 | 更新日期: 2023-09-27 18:32:06
所以IEnumerable
不能保证顺序。
这是否意味着如果您这样做myEnumerable.Skip(5)
您不能(除非您.ToList()
或之前这样做)保证将退回什么?
一旦对象被IEnumerator
产生,它们就会有一个顺序。 有些项目先出来,有些项目排在第二位,等等。 对于某些特定的实现,顺序可能有意义,对于其他实现,它可能是任意的,但仍然存在一些顺序。 Skip
实现很简单;它获得许多物品而不产生它们,然后获得其余的并产生它们。 跳过的项目是否具有任何特殊意义是调用该方法的人的责任。
调用ToList
永远不会更改序列中项的顺序,因此在调用Skip
之前添加此类调用不会更改任何内容。 另一方面,调用OrderBy
会导致顺序发生变化,可能从无意义的顺序更改为有意义的顺序。 这并不是说它是必需的,只是在某些情况下它可以成为一个有用的工具。
特定排序是否由任何特定IEnumerable<T>
保证
- 该特定实现是如何完成的,以及
- 基础集合/类的语义。
数组将以明显的顺序(从x[0]
到x[n]
)枚举其内容。同上List<T>
,它本质上是一个长度可调的数组。当然,实际的[链接]列表只能按顺序枚举。
Dictionary<K,V>
、HashSet<T>
、二叉树等的枚举顺序取决于对象的添加顺序。将具有不同顺序的相同值集合添加到二叉树中,这样构造的树的结构将有所不同(当然,退化的情况是当对象按顺序添加时,在这种情况下,树结构折叠成[有序]链表。
话虽如此,IEnumerable<T>
的任何特定实例,除非对底层集合进行任何修改,否则每次枚举时都应生成相同的值序列。当然,这假设接口的合理实现。当然,如果接口通过随机洗牌来枚举集合,则所有赌注都已关闭。
如果生产项目的实际顺序很重要,则需要
- 使用具有所需语义的集合,或
- 通过对集合或枚举进行排序来强制实施所需的顺序。
IEnumerable 是一个接口。因此,接口无法保证顺序。但是,如果您有一个实现该接口的实际对象,则该对象可能(并且经常)保证顺序。
如果使用Skip(x)
,前x
元素将被忽略,之后的所有内容都将以新的IEnumerable<T>
返回。该接口不保证它会保持秩序,但实际上它确实如此。每当您在IEnumerable<T>
上操作时,它实际上都会以线性方式通过相同的列表。例如,如果您逐行读取文件并IEnumerable<T>
则这些行将始终与它们在文件中的顺序相同(假设您不使用排序方法)。即使您使用 Where
或其他方法来筛选结果,订单仍将保留。您唯一需要担心的是实现IEnumerable<T>
的自定义集合。.NET 中的集合将按预期运行。