Sur cette page

Filtre et Filtre-Reduce simultanés

Les fonctions QtConcurrent::filter(), QtConcurrent::filtered() et QtConcurrent::filteredReduced() filtrent en parallèle les éléments d'une séquence telle que QList. QtConcurrent::filter() modifie une séquence sur place, QtConcurrent::filtered() renvoie une nouvelle séquence contenant le contenu filtré, et QtConcurrent::filteredReduced() renvoie un résultat unique.

Ces fonctions font partie du Qt Concurrent cadre.

Chacune des fonctions ci-dessus possède une variante bloquante qui renvoie le résultat final au lieu d'un QFuture. Vous les utilisez de la même manière que les variantes asynchrones.

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);

Notez que les types de résultats ci-dessus ne sont pas des objets QFuture, mais des types de résultats réels (dans ce cas, QStringList et QSet<QString>).

L'optimisation comprend

Si vous incluez l'en-tête <QtConcurrent>, tout le module Qt Concurrent et tout le module Qt Core seront inclus, ce qui peut augmenter les temps de compilation et la taille des binaires. Pour utiliser les fonctions QtConcurrent::filter(), QtConcurrent::filtered() et QtConcurrent::filteredReduced(), vous pouvez inclure un en-tête plus spécifique :

#include <QtConcurrentFilter>

Concurrent Filter

QtConcurrent::filtered() prend une séquence d'entrée et une fonction de filtrage. Cette fonction de filtrage est alors appelée pour chaque élément de la séquence, et une nouvelle séquence contenant les valeurs filtrées est renvoyée.

La fonction de filtrage doit être de la forme :

bool function(const T &t);

T doit correspondre au type stocké dans la séquence. La fonction renvoie true si l'élément doit être conservé, false s'il doit être éliminé.

Cet exemple montre comment conserver les chaînes de caractères en minuscules d'un site QStringList:

bool allLowerCase(const QString &string)
{
    return string.lowered() == string;
}

QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings, allLowerCase);

Les résultats du filtre sont disponibles à l'adresse QFuture. Consultez la documentation QFuture et QFutureWatcher pour plus d'informations sur l'utilisation de QFuture dans vos applications.

Si vous souhaitez modifier une séquence sur place, utilisez QtConcurrent::filter() :

QStringList strings = ...;
QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);

Puisque la séquence est modifiée sur place, QtConcurrent::filter() ne renvoie aucun résultat via QFuture. Cependant, vous pouvez toujours utiliser QFuture et QFutureWatcher pour surveiller l'état du filtre.

Filtres simultanés et continuités

Le résultat de l'appel à QtConcurrent::filtered() est un QFuture qui contient plusieurs résultats. Lorsque vous attachez une continuation .then() à un tel QFuture, assurez-vous d'utiliser une continuation qui prend QFuture comme paramètre, sinon seul le premier résultat sera traité :

auto keepPositive = [](int val) { return val > 0; } ;QList<int> inputs {-1, 1, 2,-3, 5 } ;auto badFuture = QtConcurrent::filtered(inputs, keepPositive) . then([](int val) {                             qDebug() << val;
                         }) ;auto goodFuture = QtConcurrent::filtered(inputs, keepPositive) .then([](QFuture<int> f) { for(auto r : f.results()) {                                  qDebug() << r;
                              } }) ;

Dans cet exemple, badFuture n'affichera qu'un seul résultat, tandis que goodFuture affichera tous les résultats.

Filtre-réduction simultané

QtConcurrent::filteredReduced() est similaire à QtConcurrent::filtered(), mais au lieu de retourner une séquence avec les résultats filtrés, les résultats sont combinés en une seule valeur en utilisant une fonction de réduction.

La fonction de réduction doit être de la forme :

V function(T &result, const U &intermediate)

T est le type du résultat final, U est le type des éléments filtrés. Notez que la valeur et le type de retour de la fonction de réduction ne sont pas utilisés.

Appelez QtConcurrent::filteredReduced() comme ceci :

void addToDictionary(QSet<QString> &dictionary, const QString &string)
{
    dictionary.insert(string);
}

QStringList strings = ...;
QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);

La fonction reduce sera appelée une fois pour chaque résultat conservé par la fonction filter, et devrait fusionner les résultats intermédiaires dans la variable result. QtConcurrent::filteredReduced() garantit qu'un seul thread appellera reduce à la fois, donc l'utilisation d'un mutex pour verrouiller la variable résultat n'est pas nécessaire. L'enum QtConcurrent::ReduceOptions permet de contrôler l'ordre dans lequel la réduction est effectuée.

Fonctionnalités supplémentaires de l'API

Utilisation d'itérateurs au lieu de séquences

Chacune des fonctions ci-dessus possède une variante qui prend une plage d'itérateurs au lieu d'une séquence. Vous les utilisez de la même manière que les variantes de séquence :

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);

Utilisation des fonctions membres

QtConcurrent::filter(), QtConcurrent::filtered(), et QtConcurrent::filteredReduced() acceptent des pointeurs vers des fonctions membres. Le type de classe de la fonction membre doit correspondre au type stocké dans la séquence :

// ne conserver que les images avec un canal alphaQList<QImage> images = ...;QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel) ;// récupérer les images en niveaux de grisQList<QImage> images =. ..;QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale) ;// créer un ensemble de tous les caractères imprimablesQList<QChar> caractères =. ..;QFuture<QSet<QChar>> ensemble = QtConcurrent::filteredReduced(characters, qOverload<>(&QChar::isPrint),                                                         qOverload<const QChar&>(&QSet<QChar>::insert));

Notez l'utilisation de qOverload, qui est nécessaire pour résoudre l'ambiguïté des méthodes qui ont plusieurs surcharges.

Notez également que lorsque vous utilisez QtConcurrent::filteredReduced(), vous pouvez mélanger librement l'utilisation des fonctions normales et des fonctions membres :

// peut mélanger les fonctions normales et les fonctions membres avec QtConcurrent::filteredReduced()// créer un dictionnaire de toutes les chaînes en minusculesextern bool allLowerCase(const QString &string) ;QStringList chaînes = ...;QFuture<QSet<QString>> lowerCase = QtConcurrent::filteredReduced(strings, allLowerCase,                                                                 qOverload<const QString&>(&QSet<QString>::insert));

// créer un collage de toutes les images en niveaux de grisextern void addToCollage(QImage &collage, const QImage &grayscaleImage) ;QList<QImage> images = ... ;QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage) ;

Utilisation d'objets fonctionnels

QtConcurrent::filter(), QtConcurrent::filtered() et QtConcurrent::filteredReduced() acceptent des objets fonction pour la fonction de filtrage. Ces objets fonction peuvent être utilisés pour ajouter un état à un appel de fonction :

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")));

Les objets fonction sont également pris en charge pour la fonction de réduction :

struct StringTransform
{
    void operator()(QString &result, const QString &value);
};

QFuture<QString> fooString =
        QtConcurrent::filteredReduced(strings, StartsWith(QLatin1String("Foo")), StringTransform());

Utilisation d'expressions lambda

QtConcurrent::filter(), QtConcurrent::filtered(), et QtConcurrent::filteredReduced() acceptent les expressions lambda pour les fonctions de filtrage et de réduction :

// 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;
    }
);

Lorsque vous utilisez QtConcurrent::filteredReduced() ou QtConcurrent::blockingFilteredReduced(), vous pouvez mélanger l'utilisation de fonctions normales, de fonctions membres et d'expressions lambda librement.

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
);

Vous pouvez également passer une expression lambda en tant qu'objet de réduction :

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;
    }
);

Envelopper les fonctions qui prennent plusieurs arguments

Si vous souhaitez utiliser une fonction de filtrage prenant plus d'un argument, vous pouvez utiliser une fonction lambda ou std::bind() pour la transformer en une fonction prenant un seul argument.

Par exemple, nous utilisons QString::contains() :

bool QString::contains(const QRegularExpression &regexp) const;

QString::contains() prend 2 arguments (y compris le pointeur "this") et ne peut pas être utilisé avec QtConcurrent::filtered() directement, parce que QtConcurrent::filtered() attend une fonction qui prend un seul argument. Pour utiliser QString::contains() avec QtConcurrent::filtered(), nous devons fournir une valeur pour l'argument regexp :

QStringList strings = ...;
QFuture<QString> future = QtConcurrent::filtered(list, [](const QString &str) {
    return str.contains(QRegularExpression("^\\S+$")); // matches strings without whitespace
});

© 2026 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.