警告

本节包含从C++自动翻译到Python的代码片段,可能包含错误。

Qt中的Java风格迭代器

用于Qt容器的Java风格迭代器。

Java风格迭代器

对于每个容器类,有两种Java风格的迭代器数据类型:一种提供只读访问,另一种提供读写访问。

注意

新代码应使用STL风格的迭代器,因为这些迭代器更高效,并且可以与Qt和STL的通用算法一起使用。

容器

只读迭代器

读写迭代器

QList , QQueue , QStack ,

QListIterator

QMutableListIterator

QSet

QSetIterator

QMutableSetIterator

QMap , QMultiMap

QMapIterator

QMutableMapIterator

QHash , QMultiHash

QHashIterator

QMutableHashIterator

在这次讨论中,我们将专注于QListQMapQSet的迭代器类型与QList的迭代器具有完全相同的接口;同样,QHash的迭代器类型与QMap的迭代器具有相同的接口。

STL风格的迭代器不同,Java风格的迭代器指向项目之间而不是直接指向项目。因此,它们要么指向容器的开始(在第一个项目之前),要么指向容器的末尾(在最后一个项目之后),要么指向两个项目之间。下图显示了包含四个项目的列表中有效迭代器位置的红箭头:

../_images/javaiterators1.png

这是一个典型的循环,用于按顺序遍历QList < QString >的所有元素:

list = {"A", "B", "C", "D"}
i = QListIterator(list)
while i.hasNext():
    s = i.next()

它的工作原理如下:要迭代的QList被传递给QListIterator构造函数。此时,迭代器位于列表中的第一个项目之前(在项目“A”之前)。然后我们调用hasNext()来检查迭代器后面是否有项目。如果有,我们调用next()来跳过那个项目。next()函数返回它跳过的项目。对于QList < QString >,该项目是QString类型的。

以下是如何在QList中向后迭代:

i = QListIterator(list)
i.toBack()
while i.hasPrevious():
    s = i.previous()

代码与向前迭代是对称的,除了我们首先调用toBack()将迭代器移动到列表中的最后一个项目之后。

下图展示了调用next()previous()对迭代器的影响:

../_images/javaiterators2.png

下表总结了QListIterator API:

函数

行为

toFront()

将迭代器移动到列表的前面(在第一个项目之前)

toBack()

将迭代器移动到列表的末尾(在最后一项之后)

hasNext()

如果迭代器不在列表的末尾,则返回 true

next()

返回下一个项目并将迭代器前进一个位置

peekNext()

返回下一个项目而不移动迭代器

hasPrevious()

如果迭代器不在列表的前面,则返回 true

previous()

返回前一个项目并将迭代器向后移动一个位置

peekPrevious()

返回前一个项目而不移动迭代器

QListIterator 在迭代时没有提供插入或删除列表项的功能。要实现这一点,你必须使用 QMutableListIterator。以下是一个使用 QMutableListIteratorQList 中删除所有奇数的示例:

i = QMutableListIterator(list)
while i.hasNext():
    if i.next() % 2 != 0:
        i.remove()

循环中的next()调用每次都会执行。它会跳过列表中的下一个项目。remove()函数会从列表中移除我们跳过的最后一个项目。调用remove()不会使迭代器失效,因此可以安全地继续使用它。这在向后迭代时同样有效:

i = QMutableListIterator(list)
i.toBack()
while i.hasPrevious():
    if i.previous() % 2 != 0:
        i.remove()

如果我们只想修改现有项的值,我们可以使用setValue()。在下面的代码中,我们将任何大于128的值替换为128:

i = QMutableListIterator(list)
while i.hasNext():
    if i.next() > 128:
        i.setValue(128)

就像remove()一样,setValue()操作的是我们跳过的最后一个项目。如果我们向前迭代,这是迭代器之前的项目;如果我们向后迭代,这是迭代器之后的项目。

next() 函数返回列表中项目的非常量引用。对于简单的操作,我们甚至不需要 setValue()

i = QMutableListIterator(list)
while i.hasNext():
    i.next() *= 2

如上所述,QSet 的迭代器类与 QList 的API完全相同。我们现在将转向 QMapIterator,它有些不同,因为它迭代的是(键,值)对。

QListIterator 类似,QMapIterator 提供了 toFront()toBack()hasNext()next()peekNext()hasPrevious()previous()peekPrevious()。通过调用 next()、peekNext()、previous() 或 peekPrevious() 返回的对象上的 key()value() 来提取键和值组件。

以下示例删除了所有首都名称以“City”结尾的(首都,国家)对:

QMap<QString, QString> map = {
    {"Paris", "France"},
    {"Guatemala City", "Guatemala"},
    {"Mexico City", "Mexico"},
    {"Moscow", "Russia"}

...
QString> = QMutableMapIterator<QString,(map)
while i.hasNext():
    if i.next().key().endsWith("City"):
        i.remove()

QMapIterator 还提供了一个 key() 和一个 value() 函数,这些函数直接在迭代器上操作,并返回迭代器跳过的最后一个项的键和值。例如,以下代码将 QMap 的内容复制到 QHash 中:

QWidget = QMap<int,()
QWidget = QHash<int,()
QWidget = QMapIterator<int,(map)
while i.hasNext():
    i.next()
    hash.insert(i.key(), i.value())

如果我们想要遍历所有具有相同值的项目,我们可以使用findNext()findPrevious()。这里有一个例子,我们删除了所有具有特定值的项目:

QWidget = QMutableMapIterator<int,(map)
while i.findNext(widget):
    i.remove()