Sorting a QList with a Comparator



  • Hi, I'm trying to implement sort() in my QAbstractTableModel and I'm having some problems.
    The underlying rows are a QList<Foo*>, where I use a class to map Foo fields to table columns.

    I tried to use qSort(rows.start(), rows.end(), lessThan) but the lessThan function has to be a
    static or global function so I'm not sure how to pass the column number to it?

    Also, the doc says: "Note that earlier versions of Qt allowed using a lessThan function that took its arguments by non-const reference. From 4.3 and on this is no longer possible, the arguments has to be passed by const reference or value."
    In this case I have pointers.

    Is there a way to sort with something like Java's Comparator (an "interface" with a compare function that takes 2 templated types)?



  • qSort also accepts a functionoid as 3rd argument, which means an object of any class with a proper bool operator()(const T &t1, const T &t2) (true means that t1 < t2 in the sorting order).



  • A sample to achieve this:

    -- test.h --

    @
    class QDebug;

    class Foo {
    public:
    friend class FooLessThan;
    friend QDebug operator<<(QDebug dbg, const Foo &foo);
    friend QDebug operator<<(QDebug dbg, const Foo *foo);
    Foo(int f, int g, int h);

    protected:
    int _f;
    int _g;
    int _h;
    };

    QDebug operator<<(QDebug dbg, const Foo &foo);
    QDebug operator<<(QDebug dbg, const Foo *foo);

    class FooLessThan
    {
    public:
    FooLessThan( int column );
    bool operator()(const Foo *left, const Foo *right ) const;

    private:
    int _column;
    };
    @

    -- test.cpp --
    @
    #include "test.h"

    #include <QDebug>

    Foo::Foo(int f, int g, int h)
    {
    _f = f;
    _g = g;
    _h = h;
    }

    QDebug operator<<(QDebug dbg, const Foo &foo)
    {
    return operator<<(dbg, &foo);
    }

    QDebug operator<<(QDebug dbg, const Foo foo)
    {
    if(foo)
    dbg.nospace() << "Foo(" << (void
    )foo << ")[f=" << foo->_f << ", g=" << foo->_g << " h=" << foo->_h << "]";
    else
    dbg.nospace() << "Foo(null)";
    return dbg.space();
    }

    FooLessThan::FooLessThan( int column )
    : _column( column )
    {
    }

    bool FooLessThan::operator()(const Foo *left, const Foo *right ) const
    {
    switch(_column) {
    case 1: return left->_f < right->_h;
    case 2: return left->_f < right->_g;
    case 3: return left->_h < right->_h;
    default: return left->_f < right->_h;
    }
    }
    @

    -- main.cpp --

    @
    #include <QList>
    #include <QDebug>

    #include "test.h"

    int main(int argc, char *argv[])
    {
    QList<Foo *> fooList;
    fooList << new Foo(1, 2, 3);
    fooList << new Foo(30, 20, 10);
    fooList << new Foo(9, 8, 1);

    qDebug() << fooList;
    FooLessThan flt(1);
    
    qSort(fooList.begin(), fooList.end(), FooLessThan(1));
    qDebug() << fooList;
    
    qSort(fooList.begin(), fooList.end(), FooLessThan(2));
    qDebug() << fooList;
    
    qSort(fooList.begin(), fooList.end(), FooLessThan(3));
    qDebug() << fooList;
    
    return 0;
    

    }
    @



  • You guys are awesome. Thanks so much. I didn't realize I could pass a functor.
    I had gotten an error before that led me to a StackOverflow posts that said you
    couldn't use member functions.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.