Итераторы в стиле STL также имеют функции key и value. Для неконстантных типов итераторов value возвращает неконстантную ссылку, позволяя нам изменять значение в ходе просмотра контейнера. Следует отметить, что хотя эти итераторы называются итераторами «в стиле STL», они существенно отличаются от итераторов STL контейнера map, которые ссылаются на pair.
Оператор цикла foreach также работает с ассоциативными контейнерами, но только с компонентом значение пар ключ—значение. Если нужны как ключи, так и значение, мы можем вызвать функции keys и values(const К &) во внутреннем цикле foreach:
QMultiMap map;
…
foreach (QString key, map.keys) {
foreach (int value, map.values(key)) {
do_something(key, value);
}
}
Обобщенные алгоритмы
В заголовочном файле объявляются глобальные шаблонные функции, которые реализуют основные алгоритмы для контейнеров. Большинство этих функций работают с итераторами в стиле STL.
Заголовочный файл STL содержит более полный набор обобщенных алгоритмов. Эти алгоритмы могут использоваться не только с STL-контейнерами, но и с Qt—контейнерами. Если STL доступен на всех ваших платформах, вероятно, нет причин не использовать STL—алгоритмы, когда в Qt отсутствует эквивалентный алгоритм. Далее мы кратко рассмотрим наиболее важные Qt—алгоритмы.
Алгоритм qFind выполняет поиск конкретного значения в контейнере. Он принимает «начальный» и «конечный» итераторы и возвращает итератор, ссылающийся на первый подходящий элемент, или «конечный» итератор, если нет подходящих элементов. В представленном ниже примере i устанавливается на list.begin + 1, a j устанавливается на list.end.
QStringList list;
list << "Emma" << "Karl" << "James" << "Mariette";
QStringList::iterator i = qFind(list.begin, list.end, "Karl");
QStringList::iterator j = qFind(list.begin, list.end, "Petra");
Алгоритм qBinaryFind выполняет поиск подобно алгоритму qFind, за исключением того, что он предполагает упорядоченность элементов в возрастающем порядке и использует двоичный поиск в отличие от линейного поиска в qFind.
Алгоритм qFill заполняет контейнер конкретным значением:
QLinkedList list(10);
qFill(list.begin, list.end, 1009);
Как и другие алгоритмы, основанные на применении итераторов, qFill может выполняться для части контейнера, если соответствующим образом установить аргументы. В следующем фрагменте программного кода первые пять элементов вектора инициализируются значением 1009, а последние пять элементов — значением 2013:
QVector vect(10);
qFill(vect.begin, vect.begin + 5, 1009);
qFill(vect.end - 5, vect.end, 2013);
Алгоритм qCopy копирует значения одного контейнера в другой.
QVector vect(list.count);
qCopy(list.begin, list.end, vect.begin);
Алгоритм qCopy может также использоваться для копирования элементов в рамках одного контейнера, если исходный диапазон и целевой диапазон не перекрываются. В следующем фрагменте программного кода мы заменяем последние два элемента списка первыми двумя элементами:
qCopy(list.begin, list.begin + 2, list.end - 2);
Алгоритм qSort сортирует элементы контейнера в порядке их возрастания.
qSort(list.begin, list.end);
По умолчанию qSort использует оператор < для сравнения элементов. Для сортировки элементов по убыванию передайте qGreater в качестве третьего аргумента (здесь T — тип элемента контейнера):
qSort(list.begin, list.end, qGreater);
Мы можем использовать третий параметр для определения пользовательского критерия сортировки. Например, ниже приводится функция сравнения «меньше, чем», которая выполняет сравнение строк QString без учета регистра:
bool insensitiveLessThan(const QString &str1, const QString &str2)
{
return str1.toLower < str2.toLower;
}
Тогда вызов qSort будет таким:
QStringList list;
qSort(list.begin, list.end, insensitiveLessThan);