原文: http://zetcode.com/gui/qt5/containers/

在 Qt5 教程的这一部分中,我们将讨论 Qt5 中的容器。 提及以下容器:QVectorQListQStringListQSetQMap

容器是通用类,用于将给定类型的项目存储在内存中。 C++ 具有标准模板库(STL),该模板库具有自己的容器。 对于 Qt,我们可以使用 Qt 容器或 STL 容器。

有两种容器:顺序容器和关联容器。 顺序容器一个接一个地存储项目,而关联容器存储键值对。 QListQVectorQLinkedList属于顺序容器; QMapQHash是关联容器的示例。

QVector

QVector是提供动态数组的模板类。 它将项目存储在相邻的内存位置,并提供基于索引的快速访问。 对于大向量,插入操作较慢,建议改用QList容器。

myvector.cpp

  1. #include <QVector>
  2. #include <QTextStream>
  3. int main(void) {
  4. QTextStream out(stdout);
  5. QVector<int> vals = {1, 2, 3, 4, 5};
  6. out << "The size of the vector is: " << vals.size() << endl;
  7. out << "The first item is: " << vals.first() << endl;
  8. out << "The last item is: " << vals.last() << endl;
  9. vals.append(6);
  10. vals.prepend(0);
  11. out << "Elements: ";
  12. for (int val : vals) {
  13. out << val << " ";
  14. }
  15. out << endl;
  16. return 0;
  17. }

该示例使用整数向量。

  1. QVector<int> vals = {1, 2, 3, 4, 5};

创建一个整数向量。

  1. out << "The size of the vector is: " << vals.size() << endl;

size()方法给出向量的大小-向量中的项数。

  1. out << "The first item is: " << vals.first() << endl;

使用first()方法检索第一项。

  1. out << "The last item is: " << vals.last() << endl;

使用last()方法可以找到向量的最后一项。

  1. vals.append(6);

append()方法将值插入向量的末尾。

  1. vals.prepend(0);

prepend()方法将值插入向量的开头。

  1. for (int val : vals) {
  2. out << val << " ";
  3. }

我们遍历for循环中的向量并打印其内容。

输出:

  1. $ ./myvector
  2. The size of the vector is: 5
  3. The first item is: 1
  4. The last item is: 5
  5. Elements: 0 1 2 3 4 5 6

QList

QList是用于创建元素列表的容器。 与QVector相似。 它存储值列表,并提供基于索引的快速访问以及快速插入和删除。 它是 Qt 中最常用的容器之一。

mylist.cpp

  1. #include <QTextStream>
  2. #include <QList>
  3. #include <algorithm>
  4. int main(void) {
  5. QTextStream out(stdout);
  6. QList<QString> authors = {"Balzac", "Tolstoy",
  7. "Gulbranssen", "London"};
  8. for (int i=0; i < authors.size(); ++i) {
  9. out << authors.at(i) << endl;
  10. }
  11. authors << "Galsworthy" << "Sienkiewicz";
  12. out << "***********************" << endl;
  13. std::sort(authors.begin(), authors.end());
  14. out << "Sorted:" << endl;
  15. for (QString author : authors) {
  16. out << author << endl;
  17. }
  18. }

该示例介绍了QList容器。

  1. QList<QString> authors = {"Balzac", "Tolstoy",
  2. "Gulbranssen", "London"};

创建一个QList容器。 它存储作家的姓名。

  1. for (int i=0; i < authors.size(); ++i) {
  2. out << authors.at(i) << endl;
  3. }

for循环中,我们遍历容器并打印其元素。 at()方法返回给定索引处的项目。

  1. authors << "Galsworthy" << "Sienkiewicz";

<<运算符用于在列表中插入两个新项目。

  1. std::sort(authors.begin(), authors.end());

std::sort()方法按升序对列表进行排序。

  1. out << "Sorted:" << endl;
  2. for (QString author : authors) {
  3. out << author << endl;
  4. }

现在我们打印排序列表。

输出:

  1. $ ./mylist
  2. Balzac
  3. Tolstoy
  4. Gulbranssen
  5. London
  6. ***********************
  7. Sorted:
  8. Balzac
  9. Galsworthy
  10. Gulbranssen
  11. London
  12. Sienkiewicz
  13. Tolstoy

QStringList

QStringList是提供字符串列表的便捷容器。 它具有基于索引的快速访问以及快速的插入和删除。

mystringlist.cpp

  1. #include <QTextStream>
  2. #include <QList>
  3. int main(void) {
  4. QTextStream out(stdout);
  5. QString string = "coin, book, cup, pencil, clock, bookmark";
  6. QStringList items = string.split(",");
  7. QStringListIterator it(items);
  8. while (it.hasNext()) {
  9. out << it.next().trimmed() << endl;
  10. }
  11. }

在示例中,我们从一个字符串创建一个字符串列表,并将元素打印到控制台中。

  1. QString string = "coin, book, cup, pencil, clock, bookmark";
  2. QStringList items = string.split(",");

QStringsplit()方法根据提供的分隔符将字符串切成子字符串。 子字符串在列表中返回。

  1. QStringListIterator it(items);

QStringListIteratorQStringList提供了 Java 样式的常迭代器。

  1. while (it.hasNext()) {
  2. out << it.next().trimmed() << endl;
  3. }

使用创建的迭代器,我们将列表的元素打印到终端。 trimmed()方法可修剪字符串元素中的空白。

输出:

  1. $ ./mystringlist
  2. coin
  3. book
  4. cup
  5. pencil
  6. clock
  7. bookmark

QSet

QSet提供具有快速查找功能的单值数学集。 值以未指定的顺序存储。

myset.cpp

  1. #include <QSet>
  2. #include <QList>
  3. #include <QTextStream>
  4. #include <algorithm>
  5. int main(void) {
  6. QTextStream out(stdout);
  7. QSet<QString> cols1 = {"yellow", "red", "blue"};
  8. QSet<QString> cols2 = {"blue", "pink", "orange"};
  9. out << "There are " << cols1.size() << " values in the set" << endl;
  10. cols1.insert("brown");
  11. out << "There are " << cols1.size() << " values in the set" << endl;
  12. cols1.unite(cols2);
  13. out << "There are " << cols1.size() << " values in the set" << endl;
  14. for (QString val : cols1) {
  15. out << val << endl;
  16. }
  17. QList<QString> lcols = cols1.values();
  18. std::sort(lcols.begin(), lcols.end());
  19. out << "*********************" << endl;
  20. out << "Sorted:" << endl;
  21. for (QString val : lcols) {
  22. out << val << endl;
  23. }
  24. return 0;
  25. }

在示例中,QSet用于存储颜色。 多次指定一种颜色值没有意义。

  1. QSet<QString> cols1 = {"yellow", "red", "blue"};
  2. QSet<QString> cols2 = {"blue", "pink", "orange"};

我们有两组颜色值。 两组中都有蓝色。

  1. out << "There are " << cols1.size() << " values in the set" << endl;

size()方法返回集合的大小。

  1. cols1.insert("brown");

我们使用insert()方法向集合中添加新值。

  1. cols1.unite(cols2);

unite((方法执行两个集合的并集。 cols1设置将具有从cols2设置插入的所有尚不存在的项目。 在我们的案例中,除了蓝色以外的所有颜色。

  1. for (QString val : cols1) {
  2. out << val << endl;
  3. }

使用for循环,我们打印cols1集中的所有项目。

  1. QList<QString> lcols = cols1.values();
  2. std::sort(lcols.begin(), lcols.end());

不支持对集合进行排序。 我们可以创建一个列表并对其进行排序。 values()方法返回一个新的QList,其中包含集合中的元素。 QList中元素的顺序未定义。

输出:

  1. $ ./myset
  2. There are 3 values in the set
  3. There are 4 values in the set
  4. There are 6 values in the set
  5. pink
  6. orange
  7. brown
  8. blue
  9. yellow
  10. red
  11. *********************
  12. Sorted:
  13. blue
  14. brown
  15. orange
  16. pink
  17. red
  18. yellow

QMap

QMap是一个存储键值对的关联数组(字典)。 它提供与键关联的值的快速查找。

myqmap.cpp

  1. #include <QTextStream>
  2. #include <QMap>
  3. int main(void) {
  4. QTextStream out(stdout);
  5. QMap<QString, int> items = { {"coins", 5}, {"books", 3} };
  6. items.insert("bottles", 7);
  7. QList<int> values = items.values();
  8. out << "Values:" << endl;
  9. for (int val : values) {
  10. out << val << endl;
  11. }
  12. QList<QString> keys = items.keys();
  13. out << "Keys:" << endl;
  14. for (QString key : keys) {
  15. out << key << endl;
  16. }
  17. QMapIterator<QString, int> it(items);
  18. out << "Pairs:" << endl;
  19. while (it.hasNext()) {
  20. it.next();
  21. out << it.key() << ": " << it.value() << endl;
  22. }
  23. }

在示例中,我们有一个字典,在其中将字符串键映射到整数值。

  1. QMap<QString, int> items = { {"coins", 5}, {"books", 3} };

创建了QMap。 它有两对。

  1. items.insert("bottles", 7);

使用insert()方法插入一对新的对。

  1. QList<int> values = items.values();
  2. out << "Values:" << endl;
  3. for (int val : values) {
  4. out << val << endl;
  5. }

我们获取字典的所有值并将其打印到控制台。 values()方法返回映射值列表。

  1. QList<QString> keys = items.keys();
  2. out << "Keys:" << endl;
  3. for (QString key : keys) {
  4. out << key << endl;
  5. }

同样,我们打印字典的所有键。 keys()方法返回一个列表,其中包含字典中的所有键。

  1. QMapIterator<QString, int> it(items);

QMapIteratorQMap的 Java 样式的迭代器。 它可用于遍历映射元素。

  1. while (it.hasNext()) {
  2. it.next();
  3. out << it.key() << ": " << it.value() << endl;
  4. }

在迭代器的帮助下,我们遍历了映射的所有元素。 key()方法返回当前键,value()方法返回当前值。

输出:

  1. $ ./myqmap
  2. Values:
  3. 3
  4. 7
  5. 5
  6. Keys:
  7. books
  8. bottles
  9. coins
  10. Pairs:
  11. books: 3
  12. bottles: 7
  13. coins: 5

自定义类排序

在下面的示例中,我们将在QList中对自定义类的对象进行排序。

book.h

  1. class Book {
  2. public:
  3. Book(QString, QString);
  4. QString getAuthor() const;
  5. QString getTitle() const;
  6. private:
  7. QString author;
  8. QString title;
  9. };

这是我们的自定义Book类的头文件。

book.cpp

  1. #include <QString>
  2. #include "book.h"
  3. Book::Book(QString auth, QString tit) {
  4. author = auth;
  5. title = tit;
  6. }
  7. QString Book::getAuthor() const {
  8. return author;
  9. }
  10. QString Book::getTitle() const {
  11. return title;
  12. }

这是Book类的实现; 我们有两种访问器方法。

sortcustomclass.cpp

  1. #include <QTextStream>
  2. #include <QList>
  3. #include <algorithm>
  4. #include "book.h"
  5. bool compareByTitle(const Book &b1, const Book &b2) {
  6. return b1.getTitle() < b2.getTitle();
  7. }
  8. int main(void) {
  9. QTextStream out(stdout);
  10. QList<Book> books = {
  11. Book("Jack London", "The Call of the Wild"),
  12. Book("Honoré de Balzac", "Father Goriot"),
  13. Book("Leo Tolstoy", "War and Peace"),
  14. Book("Gustave Flaubert", "Sentimental education"),
  15. Book("Guy de Maupassant", "Une vie"),
  16. Book("William Shakespeare", "Hamlet")
  17. };
  18. std::sort(books.begin(), books.end(), compareByTitle);
  19. for (Book book : books) {
  20. out << book.getAuthor() << ": " << book.getTitle() << endl;
  21. }
  22. }

在示例中,我们创建了一些书本对象,并使用std::sort算法对其进行排序。

  1. bool compareByTitle(const Book &b1, const Book &b2) {
  2. return b1.getTitle() < b2.getTitle();
  3. }

compareByTitle()是排序算法使用的比较功能。

  1. std::sort(books.begin(), books.end(), compareByTitle);

std::sort算法按书名对列表中的书进行排序。

输出:

  1. $ ./sortcustomclass
  2. Honoré de Balzac: Father Goriot
  3. William Shakespeare: Hamlet
  4. Gustave Flaubert: Sentimental education
  5. Jack London: The Call of the Wild
  6. Guy de Maupassant: Une vie
  7. Leo Tolstoy: War and Peace

在本章中,我们使用了 Qt 的容器。