Gleichzeitige Filter und Filter-Reduzierung
Die Funktionen QtConcurrent::filter(), QtConcurrent::filtered() und QtConcurrent::filteredReduced() filtern Elemente in einer Sequenz, wie z.B. einer QList, parallel. QtConcurrent::filter() verändert eine Sequenz in-place, QtConcurrent::filtered() gibt eine neue Sequenz zurück, die den gefilterten Inhalt enthält, und QtConcurrent::filteredReduced() gibt ein einzelnes Ergebnis zurück.
Diese Funktionen sind Teil des Qt Concurrent Frameworks.
Jede der oben genannten Funktionen hat eine blockierende Variante, die das Endergebnis anstelle von QFuture zurückgibt. Sie verwenden sie auf die gleiche Weise wie die asynchronen Varianten.
QStringList strings = ...; // each call blocks until the entire operation is finished QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strings, allLowerCase); QtConcurrent::blockingFilter(strings, allLowerCase); QSet<QString> dictionary = QtConcurrent::blockingFilteredReduced(strings, allLowerCase, addToDictionary);
Beachten Sie, dass die obigen Ergebnistypen keine QFuture Objekte sind, sondern echte Ergebnistypen (in diesem Fall QStringList und QSet<QString>).
Gleichzeitiger Filter
QtConcurrent::filtered() nimmt eine Eingabesequenz und eine Filterfunktion entgegen. Diese Filterfunktion wird dann für jedes Element in der Sequenz aufgerufen, und eine neue Sequenz mit den gefilterten Werten wird zurückgegeben.
Die Filterfunktion muss von der Form sein:
bool function(const T &t);
T muss mit dem in der Sequenz gespeicherten Typ übereinstimmen. Die Funktion gibt true
zurück, wenn das Element beibehalten werden soll, false, wenn es verworfen werden soll.
Dieses Beispiel zeigt, wie man Zeichenketten, die alle klein geschrieben sind, aus einer QStringList behalten kann:
bool allLowerCase(const QString &string) { return string.lowered() == string; } QStringList strings = ...; QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings, allLowerCase);
Die Ergebnisse des Filters werden über QFuture zur Verfügung gestellt. Weitere Informationen über die Verwendung von QFuture in Ihren Anwendungen finden Sie in der Dokumentation QFuture und QFutureWatcher.
Wenn Sie eine Sequenz an Ort und Stelle ändern möchten, verwenden Sie QtConcurrent::filter():
QStringList strings = ...; QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);
Da die Sequenz an Ort und Stelle modifiziert wird, gibt QtConcurrent::filter() keine Ergebnisse über QFuture zurück. Sie können jedoch weiterhin QFuture und QFutureWatcher verwenden, um den Status des Filters zu überwachen.
Gleichzeitiges Filter-Reduzieren
QtConcurrent::filteredReduced() ist ähnlich wie QtConcurrent::filtered(), aber anstatt eine Sequenz mit den gefilterten Ergebnissen zurückzugeben, werden die Ergebnisse mit Hilfe einer Reduktionsfunktion zu einem einzigen Wert kombiniert.
Die Reduktionsfunktion muss von der Form sein:
V function(T &result, const U &intermediate)
T ist der Typ des Endergebnisses, U ist der Typ der gefilterten Elemente. Beachten Sie, dass der Rückgabewert und der Rückgabetyp der Reduktionsfunktion nicht verwendet werden.
Rufen Sie QtConcurrent::filteredReduced() wie folgt auf:
void addToDictionary(QSet<QString> &dictionary, const QString &string) { dictionary.insert(string); } QStringList strings = ...; QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);
Die reduce-Funktion wird für jedes Ergebnis, das von der Filterfunktion gehalten wird, einmal aufgerufen und sollte die Zwischenergebnisse in die Ergebnisvariable einfügen. QtConcurrent::filteredReduced() garantiert, dass jeweils nur ein Thread reduce aufruft, so dass die Verwendung eines Mutex zum Sperren der Ergebnisvariablen nicht notwendig ist. Das QtConcurrent::ReduceOptions enum bietet eine Möglichkeit, die Reihenfolge der Reduktion zu kontrollieren.
Zusätzliche API-Funktionen
Verwendung von Iteratoren anstelle von Sequenzen
Jede der oben genannten Funktionen hat eine Variante, die einen Iteratorbereich anstelle einer Sequenz annimmt. Sie verwenden sie auf die gleiche Weise wie die Sequenzvarianten:
QStringList strings = ...; QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings.constBegin(), strings.constEnd(), allLowerCase); // filter in-place only works on non-const iterators QFuture<void> future = QtConcurrent::filter(strings.begin(), strings.end(), allLowerCase); QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings.constBegin(), strings.constEnd(), allLowerCase, addToDictionary);
Verwendung von Mitgliedsfunktionen
QtConcurrent::filter(), QtConcurrent::filtered() und QtConcurrent::filteredReduced() akzeptieren Zeiger auf Memberfunktionen. Der Klassentyp der Mitgliedsfunktion muss mit dem in der Sequenz gespeicherten Typ übereinstimmen:
// nur Bilder mit einem Alphakanal behaltenQList<QImage> images = ...;QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel);// Abrufen von GraustufenbildernQList<QImage> images = ...;QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale);// erzeugen eine Menge aller druckbaren ZeichenQList<QChar> Zeichen = ...;QFuture<QSet<QChar>> set = QtConcurrent::filteredReduced(Zeichen, qOverload<>(&QChar::isPrint), qOverload<const QChar&>(&QSet<QChar>::insert));
Beachten Sie die Verwendung von qOverload. Sie wird benötigt, um die Mehrdeutigkeit für die Methoden, die mehrere Überladungen haben, aufzulösen.
Beachten Sie auch, dass Sie bei der Verwendung von QtConcurrent::filteredReduced() die Verwendung von normalen und Mitgliedsfunktionen frei mischen können:
// kann normale Funktionen und Memberfunktionen mit QtConcurrent::filteredReduced() mischen// erstellt ein Wörterbuch aller klein geschriebenen Stringsextern bool allLowerCase(const QString &string);QStringList strings = ...;QFuture<QSet<QString>> lowerCase = QtConcurrent::filteredReduced(strings, allLowerCase, qOverload<const QString&>(&QSet<QString>::insert)); // Erstellen einer Collage aus allen Graustufenbildernextern void addToCollage(QImage &collage, const QImage &grayscaleImage);QList<QImage> images = ...;QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage);
Verwendung von Funktionsobjekten
QtConcurrent::filter(), QtConcurrent::filtered(), und QtConcurrent::filteredReduced() akzeptieren Funktionsobjekte für die Filterfunktion. Diese Funktionsobjekte können verwendet werden, um einem Funktionsaufruf einen Zustand hinzuzufügen:
struct StartsWith { StartsWith(const QString &string) : m_string(string) { } bool operator()(const QString &testString) { return testString.startsWith(m_string); } QString m_string; }; QList<QString> strings = ...; QFuture<QString> fooString = QtConcurrent::filtered(strings, StartsWith(QLatin1String("Foo")));
Funktionsobjekte werden auch für die Reduktionsfunktion unterstützt:
struct StringTransform { void operator()(QString &result, const QString &value); }; QFuture<QString> fooString = QtConcurrent::filteredReduced(strings, StartsWith(QLatin1String("Foo")), StringTransform());
Verwendung von Lambda-Ausdrücken
QtConcurrent::filter(), QtConcurrent::filtered(), und QtConcurrent::filteredReduced() akzeptieren Lambda-Ausdrücke für die Filter- und Reduktionsfunktion:
// keep only even integers QList<int> list { 1, 2, 3, 4 }; QtConcurrent::blockingFilter(list, [](int n) { return (n & 1) == 0; }); // retrieve only even integers QList<int> list2 { 1, 2, 3, 4 }; QFuture<int> future = QtConcurrent::filtered(list2, [](int x) { return (x & 1) == 0; }); QList<int> results = future.results(); // add up all even integers QList<int> list3 { 1, 2, 3, 4 }; QFuture<int> sum = QtConcurrent::filteredReduced(list3, [](int x) { return (x & 1) == 0; }, [](int &sum, int x) { sum += x; } );
Wenn Sie QtConcurrent::filteredReduced() oder QtConcurrent::blockingFilteredReduced() verwenden, können Sie die Verwendung von normalen Funktionen, Mitgliedsfunktionen und Lambda-Ausdrücken frei kombinieren.
void intSumReduce(int &sum, int x) { sum += x; } QList<int> list { 1, 2, 3, 4 }; QFuture<int> sum = QtConcurrent::filteredReduced(list, [] (int x) { return (x & 1) == 0; }, intSumReduce );
Sie können auch ein Lambda als reduce-Objekt übergeben:
bool keepEvenIntegers(int x) { return (x & 1) == 0; } QList<int> list { 1, 2, 3, 4 }; QFuture<int> sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, [](int &sum, int x) { sum += x; } );
Wrapping von Funktionen, die mehrere Argumente annehmen
Wenn Sie eine Filterfunktion verwenden möchten, die mehr als ein Argument benötigt, können Sie eine Lambda-Funktion oder std::bind()
verwenden, um sie in eine Funktion umzuwandeln, die ein Argument benötigt.
Als Beispiel verwenden wir QString::contains():
bool QString::contains(const QRegularExpression ®exp) const;
QString::contains() benötigt 2 Argumente (einschließlich des "this"-Zeigers) und kann nicht direkt mit QtConcurrent::filtered() verwendet werden, da QtConcurrent::filtered() eine Funktion erwartet, die ein Argument benötigt. Um QString::contains() mit QtConcurrent::filtered() zu verwenden, müssen wir einen Wert für das Argument regexp angeben:
QStringList strings = ...; QFuture<QString> future = QtConcurrent::filtered(list, [](const QString &str) { return str.contains(QRegularExpression("^\\S+$")); // matches strings without whitespace });
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.