枚举与索引与迭​​代

时间:2013-05-11 10:09:23

标签: c# enumeration conceptual

我已经读了Eric Lippert's blog一段时间了(这很好,你应该看看)并且在他的一个posts的评论中,他提到他无意索引一个数字序列,而只是枚举它们。

枚举和索引有什么区别,我到处搜索过?在我的搜索过程中,当迭代进入等式时,我变得更加困惑?有人可以解释这三个概念,甚至可以举一个例子吗?在你将其标记为欺骗之前,我已经看到了关于“迭代器与普查员”的一些问题,但我还是看到了正确的解释(因此问题)。感谢您的帮助。

3 个答案:

答案 0 :(得分:4)

在对文章的评论中,Eric回答了一个观察结果,即由于排列的大小呈指数级增长,因此它很快就会超过用32位表示的数字。 Eric的回答是他无意索引排列,他的意思是定义一个编号方案来获得排列的序列号。这就是为什么,他说,溢出32位并不是他关注的问题之一:他的方法允许枚举,或者只是“生成”,所有的排列都按照某些顺序排列,如同反对根据某种编号方案提供获得N-th排列的方法。

将此与question about producing N-th permutation without going through all the preceding ones中讨论的问题进行对比:在这里,作者想要对排列进行索引或给出数字,因此整数的大小是他们关注的问题。

以下是上述链接问题中讨论的索引排列的示例:

1 ABC
2 ACB
3 BAC
4 BCA
5 CAB
6 CBA

此索引方案可让您回答两个问题:

  • 特定排列的数量是多少,例如BCA? (这是4)
  • 什么是排列数X,比方说,5? (它是CAB

这个问题可能比枚举所有排列更难,因为你需要产生一个编号方案。

答案 1 :(得分:1)

从概念上讲,枚举器和迭代器都对序列知之甚少。他们通常可以:

  • 获取下一个项目
  • 检查当前元素是否是最后一个元素

修改集合时,它们的行为可能会有所不同。这些类型对于处理大量数据,流,LINQ和延迟加载非常有用,因为它们一次只能获取一个元素。要从序列中获取 i 元素,您必须迭代所有先前的元素,这是一个O(N)操作。您可以将它们视为linked list数据结构。

索引器仅适用于固定长度的内存,即使底层存储可能缩小和增长(如List<T>类型)。索引器知道什么是数据类型,以及存储需要多少,或者对对象的引用需要多少存储空间。这允许索引器从O(1)中的序列中获取任何项目,不利的一面是您必须将所有数据存储在内存中。它只是将索引乘以元素的大小,并将结果添加到起始地址 - 因此它获取所需对象的值或引用。您可以将索引器视为array数据结构。

答案 2 :(得分:1)

您只能index真实的。您可以使用arrayoperator []编制索引,也可以将list编入索引(至少在C#中,进入更正式的计算机科学的人会感到畏缩)。

您无法为IEnumerable<T>编制索引,因为枚举简单意味着您可以按顺序浏览所有项目。但是你不能跳到特定的项目。

string text = "hello";

这是枚举:

foreach( var c in text ) Console.WriteLine(c);

这使用索引:

for( int i = 0 ; i < text.Length ; i++ ) Console.WriteLine(text[i]);

这是真实的数据:

var arr = new int[15]; 

这不是真实的number中没有数据, 只是承诺提供有关枚举的数据。 您需要实现它才能拥有真正的数据:

var number = GetNumbers();

这会产生无穷无尽的数量。这不是真实的数据, 一旦你枚举它,如何生成真实数据是一种配方:

public IEnumerable<int> GetNumbers()
{
    while(true) yield return 1;
}