【问题标题】:Different types of iterators不同类型的迭代器
【发布时间】:2009-06-30 17:36:56
【问题描述】:

还有其他类型的迭代器吗?任何显示不同类型迭代器的链接?

我知道的唯一一个是 .NET 的 IEnumerable。

特别是对于 C#,但也欢迎所有其他人。

【问题讨论】:

  • 你能澄清一下你所说的其他“类型”的迭代器是什么意思吗?您是指以不同方式遍历数据结构的迭代器吗?

标签: language-agnostic iterator


【解决方案1】:

迭代器是不同语言的许多不同事物。

“不仅仅是 C# 迭代器”的一个明显例子是 C++ 迭代器,它基本上是一个序列的标记。与 C# 等价物不同,它不“知道”序列从哪里开始或结束,它只知道它当前指向哪个元素,以及如何获取下一个可能是前一个元素。

这些迭代器通常成对使用(表示序列的开始/结束),如下所示:

std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5); // create a vector (equivalent to a C# List), and populate it with the numbers 1-5

// create two iterators, pointing to the beginning and end of this vector
std::vector<int>::iterator first = v.begin();
std::vector<int>::iterator last = v.end();

std::copy(first, last, std::ostream_iterator(std::cout)); // copy all elements found between first and last, to the standard output (in the shape of a special output iterator)

或者如果我们要手动遍历它,我们会这样做:

for (vector<int>::iterator cur = v.begin(); cur != v.end(); ++cur) {
  int val = *cur; // get the value pointed to by the iterator
  cout << val; //  print that value to the standard output
}

这个效果和第一个例子中的std::copy函数一样,但是在这里你可以看到迭代器实际上是如何在序列中移动的。有趣的是你使用了一对迭代器,所以不是有一个迭代器,而是有一个“HasNext()”、“GetCurrent”和“MoveForward”函数(或类似的),你有两个迭代器,而“HasNext”是粗略地说替换为相等测试。我们测试我们在序列中前进的迭代器是否等于给定的结束迭代器。如果是这样,我们知道我们已经到达序列的末尾。

这些迭代器进一步细分为具有不同功能的不同类型。 向量的迭代器属于随机访问迭代器类别,这意味着从任何迭代器,您都可以在单个恒定时间操作中到达序列中的任何其他位置。例如,在上面的例子中,我可以通过这样做从向量的开头到结尾:

std::vector<int>::iterator last = v.begin() + 5; // advance 5 elements from begin

我也可以倒退

std::vector<int>::iterator first= v.end() - 5; // go 5 elements back from the end

然后是双向迭代器,它仍然允许您在序列中前进和后退,但一次只能一个元素(因此,您只有 ++ 和 -- 运算符,而不是 + 和 - 运算符)。例如,这些用于链接列表。没有办法在链表中以恒定时间跳过 5 个元素,因此链表实现只公开了双向迭代器,而不是随机访问。

这可以进一步缩小到前向迭代器(它只有 ++ 运算符。上面的ostream_iterator 就是一个例子。因为它包装了一个流,所以没有办法用这样的一个向后移动迭代器。

尽管大多数其他语言都实现了迭代器,但与 C# 中的迭代器非常相似。 C++ 是我所知道的唯一一个实现了更复杂(和强大)的东西

特别是,由于 C++ 迭代器与它们指向的容器分离,您可以轻松地表示子范围(例如,要表示上面向量中的前三个元素,我可以使用迭代器对 v.begin(), v.begin() + 3。另一个例子是find 函数,它在迭代器范围内搜索,并返回一个指向找到的元素的迭代器:

std::vector<int>::iterator result = std::find(v.begin(), v.end(), 3);

这个例子说要在整个向量范围内搜索第一个值为 3 的元素。它返回一个指向该元素的迭代器(如果没有找到结果,则返回结束迭代器)

这个迭代器可以与我们已有的迭代器配对,例如,我们现在可以在搜索结果和序列结尾之间的子范围内进行搜索:

std::vector<int>::iterator result2 = std::find(result + 1, v.end(), 3);

所以上面将搜索值为 3 的 next 元素,从第一个搜索结果之后的一个开始,到序列的末尾结束。当然,这样就找不到元素了,所以返回v.end()

【讨论】:

  • 谢谢 jalf。这就是我想知道的。如何找到有关 C++ 实现的迭代器类型的更多信息,以便了解更多信息?
  • 嗯,好问题。你对什么感兴趣,它们是如何实现的,它们是如何使用的,或者为什么它们是这样设计的?最终的参考当然是语言标准(您可以在 Google 上以 PDF 形式找到它的草稿),但即使对于有经验的 C++ 程序员来说,阅读量也很大。所以除此之外,我能想到的最好的是谷歌或 StackOverflow。 ;) 另一个可以帮助您查找的搜索词是 STL,即它们所属的库的名称。搜索 C++ STL 迭代器之类的东西应该会给你一个起点
  • 你也可以试试stepanovpapers.com,这个语言最初设计者的网站,几乎发明了这些迭代器。但请记住,这些概念仅在 C++ 中实现(据我所知)。其他语言有自己的迭代器形式。
  • 我在回答中添加了更多示例,但如果您有兴趣,可以提出一个专门关于 C++ 迭代器的问题。这里有很多关于 SO 的 C++ 专家,因此您应该能够轻松获得一些出色的答案。
  • 感谢您的更新。基本上还有其他类型的迭代器。有没有实现 GetElementAt/GetItemByIndex 等的?不同的迭代技术。还是它们都设计为只是 GetNext 和 Getprevious 项目,对所有东西都更通用?也像为什么 C# 家伙选择 MoveNext 而不是 MovePrevious 作为他们迭代的一部分。我只是不知道还有什么其他类型。
【解决方案2】:

Wikipedia has an excellent article on iterators:

在计算机科学中,迭代器是 允许程序员的对象 遍历 a 的所有元素 集合,无论其具体 执行。一个迭代器是 有时称为游标,尤其是 在数据库的上下文中。

它还有以下语言的代码示例:

  • C++
  • C# 和其他 .NET 语言
  • Java
  • 红宝石
  • Python
  • PHP

【讨论】:

  • 谢谢,我正在阅读,但它没有列出其他迭代器类型,例如:(猜测)一种迭代器类型必须实现,GetNext,GetPrev,并且被称为“某物”。
【解决方案3】:

Iterator 实际上是由Gang of Four 创建的设计模式的名称。设计模式只是指导方针,因此每种语言的实现方式略有不同。

但在每种语言中,您都受困于它们对内置对象的实现,您可以为自己的对象创建自己的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-22
    • 2020-02-25
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2023-03-04
    相关资源
    最近更新 更多