En esta página

Filtro concurrente y Filtro-Reduce

Las funciones QtConcurrent::filter(), QtConcurrent::filtered() y QtConcurrent::filteredReduced() filtran elementos en una secuencia como QList en paralelo. QtConcurrent::filter() modifica una secuencia in situ, QtConcurrent::filtered() devuelve una nueva secuencia con el contenido filtrado, y QtConcurrent::filteredReduced() devuelve un único resultado.

Estas funciones forman parte del Qt Concurrent marco de trabajo.

Cada una de las funciones anteriores tiene una variante de bloqueo que devuelve el resultado final en lugar de un QFuture. Se utilizan del mismo modo que las variantes asíncronas.

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

Tenga en cuenta que los tipos de resultado anteriores no son objetos QFuture, sino tipos de resultado reales (en este caso, QStringList y QSet<QString>).

Optimizar incluye

Si incluye la cabecera <QtConcurrent>, se incluirá todo el módulo Qt Concurrent con todo el módulo Qt Core, lo que puede aumentar los tiempos de compilación y el tamaño de los binarios. Para utilizar las funciones QtConcurrent::filter(), QtConcurrent::filtered(), y QtConcurrent::filteredReduced(), puede incluir una cabecera más específica:

#include <QtConcurrentFilter>

Filtro concurrente

QtConcurrent::filtered() toma una secuencia de entrada y una función de filtro. Esta función de filtrado se llama para cada elemento de la secuencia, y se devuelve una nueva secuencia que contiene los valores filtrados.

La función de filtrado debe tener la forma

bool function(const T &t);

T debe coincidir con el tipo almacenado en la secuencia. La función devuelve true si el elemento debe conservarse, false si debe descartarse.

Este ejemplo muestra cómo conservar cadenas que están todas en minúsculas de un QStringList:

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

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

Los resultados del filtro están disponibles a través de QFuture. Consulte la documentación de QFuture y QFutureWatcher para obtener más información sobre cómo utilizar QFuture en sus aplicaciones.

Si desea modificar una secuencia in situ, utilice QtConcurrent::filter():

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

Dado que la secuencia se modifica in situ, QtConcurrent::filter() no devuelve ningún resultado a través de QFuture. Sin embargo, puede seguir utilizando QFuture y QFutureWatcher para controlar el estado del filtro.

Filtrado concurrente y continuaciones

El resultado de la llamada a QtConcurrent::filtered() es un QFuture que contiene múltiples resultados. Cuando adjunte una continuación .then() a dicho QFuture, asegúrese de utilizar una continuación que tome QFuture como parámetro, de lo contrario sólo se procesará el primer resultado:

auto mantenerPositivo = [](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 buenFuturo = QtConcurrent::filtered(inputs, keepPositive) .then([](QFuture<int> f) { for(auto r : f.results()) {                                  qDebug() << r;
                              } });

En este ejemplo badFuture sólo imprimirá un único resultado, mientras que goodFuture imprimirá todos los resultados.

Filtro-Reducción Concurrente

QtConcurrent::filteredReduced() es similar a QtConcurrent::filtered(), pero en lugar de devolver una secuencia con los resultados filtrados, los resultados se combinan en un único valor usando una función de reducción.

La función de reducción debe ser de la forma

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

T es el tipo del resultado final, U es el tipo de los elementos que se filtran. Tenga en cuenta que el valor de retorno y el tipo de retorno de la función de reducción no se utilizan.

Llame a QtConcurrent::filteredReduced() así:

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

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

La función reduce será llamada una vez por cada resultado mantenido por la función filter, y debe fusionar el intermedio en la variable result. QtConcurrent::filteredReduced() garantiza que sólo un hilo llamará a reduce a la vez, por lo que no es necesario usar un mutex para bloquear la variable resultado. El enum QtConcurrent::ReduceOptions proporciona una forma de controlar el orden en el que se realiza la reducción.

Características adicionales de la API

Uso de iteradores en lugar de secuencias

Cada una de las funciones anteriores tiene una variante que toma un rango de iteradores en lugar de una secuencia. Se utilizan del mismo modo que las variantes de secuencia:

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

Uso de las funciones miembro

QtConcurrent::filter(), QtConcurrent::filtered() y QtConcurrent::filteredReduced() aceptan punteros a funciones miembro. El tipo de clase de la función miembro debe coincidir con el tipo almacenado en la secuencia:

// conservar sólo las imágenes con canal alfaQList<QImage> images = ...;QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel);// recuperar imágenes en escala de grisesQList<QImage> images = ...;QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale);// crear un conjunto de todos los caracteres imprimiblesQList<QChar> caracteres = ...;QFuture<QSet<QChar>> conjunto = QtConcurrent::filtradoReducido(caracteres, qOverload<>(&QChar::isPrint),                                                         qOverload<const QChar&>(&QSet<QChar>::insert));

Nótese el uso de qOverload. Es necesario para resolver la ambigüedad de los métodos, que tienen múltiples sobrecargas.

También tenga en cuenta que cuando se utiliza QtConcurrent::filteredReduced(), puede mezclar el uso de funciones normales y funciones miembro libremente:

// puede mezclar funciones normales y funciones miembro con QtConcurrent::filteredReduced()// crear un diccionario de todas las cadenas en minúsculasextern bool allLowerCase(const QString &cadena);QStringList cadenas = ...;QFuture<QSet<QString>> minúsculas = QtConcurrent::filteredReduced(cadenas, allLowerCase,                                                                 qOverload<const QString&>(&QSet<QString>::insert));

// crear un collage de todas las imágenes en escala de grisesextern void addToCollage(QImage &collage, const QImage &grayscaleImage);QList<QImage> images = ...;QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage);

Uso de objetos de función

QtConcurrent::filter(), QtConcurrent::filtered(), y QtConcurrent::filteredReduced() aceptan objetos de función para la función de filtrado. Estos objetos de función pueden usarse para añadir estado a una llamada de función:

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

También se admiten objetos de función para la función reducir:

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

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

Uso de expresiones lambda

QtConcurrent::filter(), QtConcurrent::filtered(), y QtConcurrent::filteredReduced() aceptan expresiones lambda para las funciones filter y reduce:

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

Al usar QtConcurrent::filteredReduced() o QtConcurrent::blockingFilteredReduced(), puede mezclar libremente el uso de funciones normales, funciones miembro y expresiones lambda.

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

También puede pasar una lambda como objeto reduce:

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

Envolver funciones que toman múltiples argumentos

Si desea utilizar una función de filtro que tome más de un argumento, puede utilizar una función lambda o std::bind() para transformarla en una función que tome un argumento.

Como ejemplo, utilizamos QString::contains():

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

QString::contains() toma 2 argumentos (incluido el puntero "this") y no puede usarse con QtConcurrent::filtered() directamente, porque QtConcurrent::filtered() espera una función que tome un argumento. Para usar QString::contains() con QtConcurrent::filtered() tenemos que proporcionar un valor para el argumento 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.