Qtのリストフィルタリング徹底解説:QRegExp/QRegularExpressionの活用法

2025-05-26

まず、重要な点として、QRegExp::filterList()という名前の直接的な関数はQtのドキュメントには存在しません。

しかし、QRegExp(またはQt 5以降で推奨されているQRegularExpression)の機能を使ってリストをフィルタリングするという意味合いで、この表現を使われている可能性があります。

そのため、ここでは「QRegExp(正規表現)を使ってリストをフィルタリングする方法」という文脈でご説明します。

QRegExpとは?

QRegExpは、Qtフレームワークが提供する正規表現を扱うためのクラスです。正規表現とは、文字列の中から特定のパターンに一致する部分を検索したり、置換したりするための強力なツールです。

リストのフィルタリングにおけるQRegExpの役割

文字列のリスト(例えばQStringList)から、特定の条件に合致する要素だけを抽出したい場合に、QRegExpが非常に役立ちます。

具体的には、QStringListクラスにはfilter()というメソッドがあり、このメソッドにQRegExpオブジェクトを渡すことで、正規表現によるフィルタリングを行うことができます。

QStringList::filter(const QRegExp &rx) const の例

以下に、QRegExpを使ってQStringListをフィルタリングする基本的な例を示します。

#include <QCoreApplication>
#include <QStringList>
#include <QRegExp>
#include <QDebug>

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

    QStringList originalList;
    originalList << "apple" << "banana" << "apricot" << "grape" << "orange";

    // "ap" で始まる文字列をフィルタリングする正規表現
    QRegExp regex("^ap.*", Qt::CaseInsensitive); // '^' は行頭、'.*' は任意の文字が0回以上

    // filter() メソッドを使ってリストをフィルタリング
    QStringList filteredList = originalList.filter(regex);

    qDebug() << "Original List:" << originalList;
    qDebug() << "Filtered List (starts with 'ap'):" << filteredList;

    // "e" で終わる文字列をフィルタリングする正規表現
    QRegExp regex2(".*e$", Qt::CaseInsensitive); // '.' は任意の1文字、'*' は0回以上、'$' は行末

    QStringList filteredList2 = originalList.filter(regex2);
    qDebug() << "Filtered List (ends with 'e'):" << filteredList2;

    return a.exec();
}

実行結果

Original List: ("apple", "banana", "apricot", "grape", "orange")
Filtered List (starts with 'ap'): ("apple", "apricot")
Filtered List (ends with 'e'): ("apple", "grape", "orange")

Qt 5以降では、QRegExpよりも高性能でPOSIX準拠の正規表現エンジンであるQRegularExpressionの使用が推奨されています。新しいコードを書く際は、QRegularExpressionを使用することをお勧めします。

QRegularExpressionを使ったフィルタリングの例は、上記のQRegExpQRegularExpressionに置き換えるだけでほぼ同様に機能します。

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression> // QRegularExpression をインクルード
#include <QDebug>

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

    QStringList originalList;
    originalList << "apple" << "banana" << "apricot" << "grape" << "orange";

    // "ap" で始まる文字列をフィルタリングする正規表現 (QRegularExpression版)
    QRegularExpression regex("^ap.*", QRegularExpression::CaseInsensitiveOption); 

    QStringList filteredList = originalList.filter(regex); // filter() メソッドは QRegularExpression も受け入れます

    qDebug() << "Original List:" << originalList;
    qDebug() << "Filtered List (starts with 'ap'):" << filteredList;

    return a.exec();
}
  • 新しいコードでは、QRegExpよりもQRegularExpressionの使用が推奨されます。
  • このフィルタリングは、QStringList::filter()メソッドにQRegExp(またはQRegularExpression)オブジェクトを渡すことで実現されます。
  • QRegExp::filterList()」という表現は、QRegExpを使ってQStringListなどのリストをフィルタリングする処理を指している可能性が高いです。
  • QRegExp::filterList()という直接の関数はQtにはありません。


正規表現は強力なツールですが、その複雑さゆえにエラーや意図しない挙動が発生しやすいものです。

正規表現のパターンが正しくない(最も多いエラー)

  • トラブルシューティング

    • 正規表現テスターの利用
      オンラインの正規表現テスター(例: regex101.com, regexr.com)を使って、作成した正規表現が意図した文字列にマッチするかどうかをテストします。これにより、パターン自体の問題を特定できます。
    • 正規表現を単純化する
      複雑な正規表現の場合、より単純なパターンから始めて、少しずつ複雑にしていくことで、どこで問題が発生しているかを見つけやすくなります。
    • Qtのデバッグ出力
      QRegExpQRegularExpressionpattern()errorString()メソッドを使って、設定されているパターンやエラーメッセージを確認します。QRegularExpressionの場合、isValid()で正規表現が有効か確認できます。
    QRegularExpression regex("invalid[pattern("); // 意図的にエラーのあるパターン
    if (!regex.isValid()) {
        qDebug() << "Regex Error:" << regex.errorString();
    }
    
  • 原因

    • 特殊文字のエスケープ忘れ
      正規表現の特殊文字(例: . * + ? \ ( ) [ ] { } ^ $ |)をリテラル文字として扱いたい場合、前に\を付けてエスケープする必要があります。C++の文字列リテラルでは\自体もエスケープが必要なので、\\と二重に記述することが多いです。
      • 例: ファイル拡張子.txtにマッチさせたい場合、".txt"ではなく"\\.txt"と記述する必要があります。
    • 正規表現の構文ミス
      正規表現の構文自体が間違っている。例えば、括弧の閉じ忘れ、文字クラスの範囲指定ミスなど。
    • 貪欲マッチと非貪欲マッチの混同
      *+などの量指定子はデフォルトで「貪欲(greedy)」にマッチします。つまり、可能な限り長い文字列にマッチしようとします。これにより、意図しない部分までマッチしてしまうことがあります。最短マッチさせたい場合は、*?+?のように?を付けます(非貪欲マッチ)。
    • アンカー(^, $)の使用ミス
      ^は文字列の先頭、$は文字列の末尾にマッチします。これらを付け忘れると、文字列中のどこかにパターンが含まれていればマッチしてしまいます。完全に一致させたい場合は、両端に^$を付ける必要があります。
    • 文字クラスの誤解
      \d(数字)、\w(単語文字)、\s(空白文字)などの短縮形や、[a-zA-Z]などの文字クラスの範囲が意図と異なる。
  • エラー
    意図した文字列がフィルタリングされない、または予期しない文字列がフィルタリングされてしまう。

大文字・小文字の区別(Case Sensitivity)

  • トラブルシューティング

    • QRegExpの場合、コンストラクタの2番目の引数やsetCaseSensitivity()Qt::CaseSensitive(区別する)またはQt::CaseInsensitive(区別しない)を指定します。
    • QRegularExpressionの場合、コンストラクタの2番目の引数やsetPatternOptions()QRegularExpression::CaseInsensitiveOptionなどを指定します。
    // 大文字・小文字を区別しない
    QRegExp rx("apple", Qt::CaseInsensitive); 
    QRegularExpression re("apple", QRegularExpression::CaseInsensitiveOption); 
    
  • 原因
    QRegExpQRegularExpressionのデフォルトの挙動、または設定ミス。

  • エラー
    大文字・小文字を区別してフィルタリングしたいのに区別されない、またはその逆。

パターン構文の選択ミス

  • トラブルシューティング

    • QRegExp::patternSyntax()で現在の構文を確認します。
    • QRegExp::Wildcardを使いたい場合は、正規表現の代わりに*?などのワイルドカード記号を使います。
    QRegExp rx("*.txt", Qt::CaseSensitive, QRegExp::Wildcard); // ワイルドカードとして解釈
    
  • 原因
    QRegExpはデフォルトでPerl互換の構文を使用しますが、QRegExp::setPatternSyntax()QRegExp::Wildcard(シェル風のワイルドカード)やQRegExp::FixedString(固定文字列)に切り替えることができます。これにより、正規表現の解釈が変わります。

  • エラー
    特定の正規表現構文が期待通りに機能しない。

QRegExpとQRegularExpressionの混同(Qt 5移行)

  • トラブルシューティング
    • 可能であれば、コードをQRegularExpressionに移行します。QRegularExpressionはよりPerl互換性が高く、高性能です。
    • QRegExpからQRegularExpressionへの移行の際には、正規表現の構文やオプションの指定方法が若干異なる点に注意が必要です(例: 大文字・小文字のオプションなど)。
  • 原因
    QRegExpは古い正規表現エンジンであり、バグやパフォーマンスの問題が知られています。Qt 5以降ではQRegularExpressionが推奨されています。
  • エラー
    Qt 5以降でQRegExpを使っているが、意図しない挙動やパフォーマンスの問題が発生する。

空文字列のマッチ

  • トラブルシューティング
    • 空文字列を明示的に除外したい場合は、+(1回以上)を使うか、マッチ後に結果の文字列が空でないかを確認します。
    • 空文字列にマッチさせたくない場合は、正規表現のパターンを調整します。
  • 原因
    正規表現によっては空文字列にもマッチしてしまう場合があります(例: .*)。
  • エラー
    空文字列をフィルタリングしたい(またはフィルタリングしたくない)のにうまくいかない。

パフォーマンスの問題

  • トラブルシューティング
    • 正規表現の最適化
      よりシンプルで効率的な正規表現を検討します。
    • QRegularExpressionへの移行
      QRegExpを使用している場合、QRegularExpressionに移行することでパフォーマンスが大幅に改善される可能性があります。
    • 複数スレッドでの処理
      大量のデータを処理する場合、フィルタリング処理を別のスレッドで行うことでUIのフリーズを防ぎ、ユーザー体験を向上させることができます。
    • フィルタリングロジックの再考
      正規表現が本当に最適解なのか、より単純な文字列操作(QString::contains(), QString::startsWith(), QString::endsWith()など)で代用できないかを検討します。
  • 原因
    • 複雑すぎる正規表現
      非効率的な正規表現は処理が遅くなります。特にバックトラックが多いパターン(例: (a|a)*)は注意が必要です。
    • 非常に大きなリスト
      フィルタリング対象のリストが非常に大きい場合、個々のマッチングが速くても全体として時間がかかることがあります。
  • エラー
    大量の文字列をフィルタリングする際に処理が遅くなる。


Qtでリストを正規表現でフィルタリングする最も一般的な方法は、QStringListクラスが提供するfilter()メソッドを使用することです。このfilter()メソッドは、QRegExpまたはQRegularExpressionのオブジェクトを引数として受け取ります。

必要なヘッダファイル

  • #include <QDebug> (結果を出力するため)
  • #include <QRegularExpression>QRegularExpressionを使用する場合)
  • #include <QRegExp>QRegExpを使用する場合)
  • #include <QStringList>

例1: 特定の文字列で始まる要素をフィルタリングする

最も基本的な例です。リストの中から「ap」で始まるすべての文字列を抽出します。大文字・小文字を区別しない設定にします。

QRegExp を使用した例

#include <QCoreApplication>
#include <QStringList>
#include <QRegExp>
#include <QDebug>

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

    QStringList originalList;
    originalList << "apple" << "banana" << "Apricot" << "grape" << "orange" << "API";

    // 正規表現: '^ap.*'
    // '^' : 文字列の先頭
    // 'ap' : リテラルの 'ap'
    // '.*' : 任意の文字が0回以上続く
    // Qt::CaseInsensitive : 大文字・小文字を区別しない
    QRegExp regex("^ap.*", Qt::CaseInsensitive);

    qDebug() << "--- QRegExp を使用した例 (特定の文字列で始まる) ---";
    qDebug() << "元のリスト:" << originalList;

    QStringList filteredList = originalList.filter(regex);

    qDebug() << "フィルタリング後のリスト (先頭が 'ap' (大文字小文字無視)): " << filteredList;
    // 期待される出力: ("apple", "Apricot", "API")

    return a.exec();
}

QRegularExpression を使用した例 (推奨)

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression> // QRegularExpression をインクルード
#include <QDebug>

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

    QStringList originalList;
    originalList << "apple" << "banana" << "Apricot" << "grape" << "orange" << "API";

    // 正規表現: '^ap.*'
    // QRegularExpression::CaseInsensitiveOption : 大文字・小文字を区別しないオプション
    QRegularExpression regex("^ap.*", QRegularExpression::CaseInsensitiveOption);

    qDebug() << "--- QRegularExpression を使用した例 (特定の文字列で始まる) ---";
    qDebug() << "元のリスト:" << originalList;

    QStringList filteredList = originalList.filter(regex); // filter() は QRegularExpression も受け入れます

    qDebug() << "フィルタリング後のリスト (先頭が 'ap' (大文字小文字無視)): " << filteredList;
    // 期待される出力: ("apple", "Apricot", "API")

    return a.exec();
}

例2: 特定のパターンを含む要素をフィルタリングする

リストの中から、任意の場所に「an」という文字列を含む要素を抽出します。

QRegularExpression を使用した例

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression>
#include <QDebug>

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

    QStringList dataList;
    dataList << "banana" << "apple" << "orange" << "pineapple" << "mango";

    // 正規表現: 'an'
    // これは単に部分文字列 'an' にマッチします。
    QRegularExpression regex("an");

    qDebug() << "--- QRegularExpression を使用した例 (特定のパターンを含む) ---";
    qDebug() << "元のリスト:" << dataList;

    QStringList filteredList = dataList.filter(regex);

    qDebug() << "フィルタリング後のリスト ('an' を含む): " << filteredList;
    // 期待される出力: ("banana", "orange", "pineapple", "mango")

    return a.exec();
}

例3: ファイル拡張子でフィルタリングする

ファイル名のリストから、.txtまたは.logの拡張子を持つファイルだけを抽出します。

QRegularExpression を使用した例

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression>
#include <QDebug>

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

    QStringList fileList;
    fileList << "document.txt" << "image.png" << "report.log" << "notes.txt" << "backup.zip";

    // 正規表現: '\.(txt|log)$'
    // '\.' : リテラルの '.' をエスケープ
    // '(txt|log)' : 'txt' または 'log' のいずれかにマッチするグループ
    // '$' : 文字列の末尾
    QRegularExpression regex("\\.(txt|log)$");

    qDebug() << "--- QRegularExpression を使用した例 (ファイル拡張子でフィルタリング) ---";
    qDebug() << "元のリスト:" << fileList;

    QStringList filteredList = fileList.filter(regex);

    qDebug() << "フィルタリング後のリスト (.txt または .log): " << filteredList;
    // 期待される出力: ("document.txt", "report.log", "notes.txt")

    return a.exec();
}

例4: 数字のみを含む要素をフィルタリングする

リストの中から、完全に数字のみで構成されている文字列を抽出します。

QRegularExpression を使用した例

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression>
#include <QDebug>

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

    QStringList mixedList;
    mixedList << "123" << "abc" << "45678" << "text1" << "90";

    // 正規表現: '^\d+$'
    // '^' : 文字列の先頭
    // '\d' : 数字 (0-9) にマッチ
    // '+' : 直前の要素が1回以上繰り返す
    // '$' : 文字列の末尾
    QRegularExpression regex("^\\d+$");

    qDebug() << "--- QRegularExpression を使用した例 (数字のみ) ---";
    qDebug() << "元のリスト:" << mixedList;

    QStringList filteredList = mixedList.filter(regex);

    qDebug() << "フィルタリング後のリスト (数字のみ): " << filteredList;
    // 期待される出力: ("123", "45678", "90")

    return a.exec();
}

QStringList::filter()はマッチする要素を抽出します。特定のパターンではない要素を抽出したい場合は、少し工夫が必要です。フィルタリング後に手動でループを回すか、あるいはラムダ式とstd::remove_ifなどを使用します。

ここでは、単純なループで「Qで始まる文字列」を除外する例を示します。

#include <QCoreApplication>
#include <QStringList>
#include <QRegularExpression>
#include <QDebug>

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

    QStringList programmingLanguages;
    programmingLanguages << "C++" << "Python" << "Java" << "Qt" << "QML" << "JavaScript";

    // 除外したいパターン: 'Q' で始まる (大文字・小文字を区別しない)
    QRegularExpression excludeRegex("^Q.*", QRegularExpression::CaseInsensitiveOption);

    QStringList excludedList; // 一時的に除外する要素を保持
    QStringList resultList;   // 最終的な結果

    qDebug() << "--- 除外フィルタリングの例 (Qで始まる文字列を除外) ---";
    qDebug() << "元のリスト:" << programmingLanguages;

    for (const QString &item : programmingLanguages) {
        if (!item.contains(excludeRegex)) { // 正規表現にマッチしない場合
            resultList.append(item);
        }
    }

    qDebug() << "フィルタリング後のリスト (Qで始まるものを除外): " << resultList;
    // 期待される出力: ("C++", "Python", "Java", "JavaScript")

    return a.exec();
}

これらの例は、QtでQRegExpまたはQRegularExpressionを使ってリストをフィルタリングする基本的な方法を示しています。

  • QStringList::filter(const QRegularExpression &re) const
  • QStringList::filter(const QRegExp &rx) const


単純なループと条件分岐

最も基本的で直接的な方法です。リストの各要素を順番にチェックし、条件に合うものだけを新しいリストに追加します。正規表現が不要な、単純な文字列比較に適しています。

ユースケース

  • 文字列の長さ、数値への変換など、より複雑なカスタムロジック
  • 文字列が完全に一致するか (QString::operator==())
  • 特定の文字列で終わっているか (QString::endsWith())
  • 特定の文字列で始まっているか (QString::startsWith())
  • 特定の文字列が含まれているか (QString::contains())


文字列 "apple" を含む要素をフィルタリング

#include <QCoreApplication>
#include <QStringList>
#include <QDebug>

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

    QStringList originalList;
    originalList << "red apple" << "green banana" << "sweet apple pie" << "blue car";

    QStringList filteredList;
    const QString searchText = "apple";

    qDebug() << "--- 代替方法1: 単純なループと条件分岐 ---";
    qDebug() << "元のリスト:" << originalList;

    for (const QString &item : originalList) {
        if (item.contains(searchText, Qt::CaseInsensitive)) { // 大文字小文字を無視して 'apple' を含むか
            filteredList.append(item);
        }
    }

    qDebug() << "フィルタリング後のリスト ('apple' を含む):" << filteredList;
    // 期待される出力: ("red apple", "sweet apple pie")

    return a.exec();
}

利点

  • どんな複雑なフィルタリングロジックでも記述できる。
  • 正規表現が不要な場合、オーバーヘッドが少ない。
  • 非常に分かりやすく、理解しやすい。

欠点

  • 正規表現のような強力なパターンマッチングはできない。
  • コードが冗長になりがち。

STLアルゴリズムとラムダ式 (std::copy_if, std::remove_if)

C++標準ライブラリのアルゴリズムとラムダ式を組み合わせることで、より簡潔で表現力豊かなコードでフィルタリングを行うことができます。

  • std::remove_if
    条件に合う要素をリストの末尾に移動させ、削除すべき要素の範囲を返します。その後、erase()で実際に削除します。元のリストが変更されます。
  • std::copy_if
    条件に合う要素を別のコンテナにコピーします。元のリストは変更されません。

ユースケース
ループと同様に、様々なカスタムロジックを簡潔に記述したい場合。

例 (std::copy_if)
数字のみを含む要素をフィルタリング

#include <QCoreApplication>
#include <QStringList>
#include <QDebug>
#include <algorithm> // std::copy_if, std::back_inserter, std::all_of
#include <cctype>    // ::isdigit

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

    QStringList originalList;
    originalList << "123" << "abc" << "45678" << "text1" << "90" << ""; // 空文字列も含む

    QStringList filteredList;

    qDebug() << "--- 代替方法2: STLアルゴリズムとラムダ式 (std::copy_if) ---";
    qDebug() << "元のリスト:" << originalList;

    // ラムダ式でフィルタリング条件を定義
    // item.toStdString() で QString を std::string に変換し、
    // std::all_of と ::isdigit を使ってすべての文字が数字であるかチェック
    // QChar::isDigit() を使えば toStdString() は不要です。
    std::copy_if(originalList.begin(), originalList.end(),
                 std::back_inserter(filteredList),
                 [](const QString &item) {
                     // Qtの方法: QChar::isDigit() を使う
                     if (item.isEmpty()) return false; // 空文字列は数字ではないと判断
                     for (QChar c : item) {
                         if (!c.isDigit()) {
                             return false;
                         }
                     }
                     return true;

                     // C++標準の方法: std::all_of と ::isdigit を使う (QStringをstd::stringに変換が必要)
                     // return !item.isEmpty() && std::all_of(item.toStdString().begin(), item.toStdString().end(), ::isdigit);
                 });

    qDebug() << "フィルタリング後のリスト (数字のみ):" << filteredList;
    // 期待される出力: ("123", "45678", "90")

    return a.exec();
}

利点

  • 汎用的なアルゴリズムなので、様々なコンテナで利用できる。
  • コードがより簡潔で、関数型プログラミングのようなスタイルになる。

欠点

  • QStringstd::string間の変換が必要になる場合がある(上記のQChar::isDigit()のようにQtのAPIを使えば避けられることが多い)。
  • 初学者にはラムダ式やSTLアルゴリズムの理解に少し学習コストがかかる。

UIアプリケーション(QListView, QTableViewなど)でデータを表示している場合、データのリスト自体を変更せずに、表示されるデータをフィルタリングする強力な方法です。これは特に大規模なデータセットや動的なフィルタリングが必要な場合に非常に有効です。

ユースケース

  • 大量のデータを扱う場合、効率的な表示フィルタリングが必要な場合。
  • フィルタリング条件が頻繁に変わる場合(検索バーに入力されたテキストに基づいてフィルタリングするなど)。
  • ユーザーインターフェース(GUI)上でリストやテーブルの表示内容をフィルタリングしたい場合。

基本的な流れ

  1. データを提供するモデル(例: QStringListModelやカスタムモデル)を作成します。
  2. QSortFilterProxyModelのインスタンスを作成し、そのsetSourceModel()でデータモデルを設定します。
  3. QSortFilterProxyModelをビュー(QListViewなど)に設定します。
  4. QSortFilterProxyModel::setFilterRegExp()(またはsetFilterRegularExpression())やsetFilterKeyColumn()setFilterRole()などを使ってフィルタリング条件を設定します。

例 (概念的なコード - 実際のUIアプリケーションの一部)

// これは完全な実行可能なコードではなく、QSortFilterProxyModelの使用例を示す概念です。
// UIアプリケーションのメインウィンドウクラスなどで使用されます。

#include <QApplication>
#include <QStringListModel>
#include <QListView>
#include <QSortFilterProxyModel>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QRegularExpression> // QRegExp でも同様に使用可能

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

    // 1. 元データモデル
    QStringListModel *sourceModel = new QStringListModel();
    QStringList data;
    data << "Apple" << "Banana" << "Apricot" << "Grape" << "Orange" << "API";
    sourceModel->setStringList(data);

    // 2. プロキシモデル (フィルタリングを担当)
    QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel();
    proxyModel->setSourceModel(sourceModel);
    // proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); // 大文字小文字を無視

    // 3. UI部品
    QListView *listView = new QListView();
    listView->setModel(proxyModel); // プロキシモデルをビューに設定

    QLineEdit *filterLineEdit = new QLineEdit();
    filterLineEdit->setPlaceholderText("フィルタリングキーワードを入力...");

    // フィルタリングロジックの接続
    // QLineEdit のテキスト変更シグナルを捕らえ、プロキシモデルのフィルタリング条件を更新
    QObject::connect(filterLineEdit, &QLineEdit::textChanged, proxyModel,
                     [proxyModel](const QString &text){
                         // QRegularExpression でフィルタリング条件を設定
                         QRegularExpression regex(text, QRegularExpression::CaseInsensitiveOption);
                         proxyModel->setFilterRegularExpression(regex);
                     });

    // レイアウト設定
    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);
    layout->addWidget(filterLineEdit);
    layout->addWidget(listView);
    window->setWindowTitle("QSortFilterProxyModel Example");
    window->resize(300, 400);
    window->show();

    return a.exec();
}

利点

  • UIをブロックせずに動的なフィルタリングが可能。
  • ソート機能も同時に提供できる。
  • 非常に大規模なデータセットでも効率的に動作する。
  • UIとデータの分離が明確になり、MVC(Model-View-Controller)パターンに沿った設計が可能。

欠点

  • モデル/ビューフレームワークの理解が必要となるため、学習コストがある。
  • シンプルなスクリプトやCLIツールにはオーバーヘッドが大きい。

QRegExp::filterList()という関数は存在しませんが、Qtでリストをフィルタリングする方法は多岐にわたります。

  • UIアプリケーション
    QSortFilterProxyModelが、データの表示とフィルタリングを分離する最も強力で推奨される方法です。
  • カスタムロジックやSTLアルゴリズム
    ラムダ式とstd::copy_ifなどを組み合わせることで、柔軟かつ簡潔に記述できます。
  • より単純な条件
    ループとQString::contains()/startsWith()/endsWith()が適しています。
  • 単純なフィルタリング
    QStringList::filter(QRegExp/QRegularExpression) が最も直接的で推奨される方法です。