gpt4 book ai didi

c++ - 处理接近大型数据集时加快 QSortFilterProxyModel 过滤

转载 作者:搜寻专家 更新时间:2023-10-31 02:14:21 25 4
gpt4 key购买 nike

之前,我问过a question关于多列过滤,我们需要表示适合多个过滤模式的行。

现在,当处理大表时(,我的意思是大约 200,000 行和 4 列)如果我们有一个那么大的表,过滤会变慢(通常这对于过滤器的前 2 个字符来说是最差的模式)。

那么你对此有何建议?

注意:我有自己的基于this 的高性能源数据模型(而不是QStandardItemModel)示例女巫在大约 1 秒内为我提供了该行数的 View

编辑 1

从此改变我的方法:

bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
if (/* filtering is enable*/) {
bool _res = sourceModel()->data(sourceModel()->index(source_row, 0, source_parent)).toString().contains( /*RegExp for column 0*/);
for (int col = 0; col < columnCount(); col++) {
_res &= sourceModel()->data(sourceModel()->index(source_row, col + 1, source_parent)).toString().contains(/*RegExp for column col + 1*/);
}
return _res;
}
return true;

为此:

bool DataFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
if (_enable) {
return (sourceModel()->index(source_row, 0, source_parent.child(source_row, 0)).data().toString().contains( /*string for column 0*/ ))
&& sourceModel()->index(source_row, 1, source_parent.child(source_row, 1)).data().toString().contains(/*string for column 1*/))
&& sourceModel()->index(source_row, 2, source_parent.child(source_row, 2)).data().toString().contains(/*string for column 2*/))
&& sourceModel()->index(source_row, 3, source_parent.child(source_row, 3)).data().toString().contains(/*string for column 3*/));
}
return true;
}

看起来很完美。现在过滤工作就像魅力一样毫不拖延

最佳答案

如果项目数量非常多,您无法一次加载它们,您可以尝试仅在 View 中需要时才分批添加项目。这可以通过覆盖 canFetchMore() 来完成和 fetchMore() .看看 Fetch More Example .请注意,这是 QSqlQueryModel 在内部从数据库加载大型模型的方式,请参阅 here .

以下是如何使用这种方法实现您的模型:

#include <QApplication>
#include <QtWidgets>

class MyTableModel : public QAbstractTableModel{
public:
explicit MyTableModel(int rowCount, QObject* parent=nullptr)
:QAbstractTableModel(parent),currentRowCount(0),wholeRowCount(rowCount){}
~MyTableModel(){}

int rowCount(const QModelIndex &parent) const override{
if(parent.isValid()) return 0;
return currentRowCount;
}
int columnCount(const QModelIndex &parent) const override{
if(parent.isValid()) return 0;
return 2;
}

QVariant data(const QModelIndex &index, int role) const override{
Q_ASSERT(index.row()<currentRowCount);
QVariant val;
if(role== Qt::DisplayRole || role== Qt::EditRole){
switch(index.column()){
case 0:
val= QString("#%1").arg(index.row()+1, 8, 10, QChar('0'));
break;
case 1:
val= rows[index.row()];
break;
}
}
return val;
}

bool canFetchMore(const QModelIndex &parent) const override{
if(parent.isValid()) return false;
return (currentRowCount < wholeRowCount);
}

void fetchMore(const QModelIndex& /* index */) override{
int toFetch= qMin(52, wholeRowCount-currentRowCount);
char ch = 'A';
beginInsertRows(QModelIndex(), currentRowCount, currentRowCount+toFetch-1);
for(int i=0; i<toFetch; i++){
rows+= QString(QChar(ch));
if(ch == 'Z') ch = 'A';
else ch++;
}
currentRowCount+= toFetch;
endInsertRows();
}

private:
int currentRowCount;
int wholeRowCount;
QStringList rows;
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QWidget w;
QVBoxLayout layout(&w);
QLineEdit filterLineEdit;
QTableView tableView;
layout.addWidget(&filterLineEdit);
layout.addWidget(&tableView);

MyTableModel model(200000);
QSortFilterProxyModel proxyModel;
proxyModel.setSourceModel(&model);
proxyModel.setFilterKeyColumn(-1);
tableView.setModel(&proxyModel);

QObject::connect(&filterLineEdit, &QLineEdit::textChanged, [&](){
proxyModel.setFilterFixedString(filterLineEdit.text());
});

w.show();

return a.exec();
}

如果您确定真正的瓶颈是过滤,您可能还想避免使用正则表达式,如@DmitrySazonov 所述,子类 QSortFilterProxyModel,覆盖 filterAcceptsRow()并在那里提供您的算法,而不是使用一般的基于 QRegExp 的过滤器。

另一件需要考虑的事情是当过滤器变窄时避免检查已经过滤的行,看看 this question .

关于c++ - 处理接近大型数据集时加快 QSortFilterProxyModel 过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40027252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com