Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, March 2008
Using the qsort less than function


Message 1 in thread

Using Qt 4.4 beta 1 on windows XP:

I would like to use qSort on a QList to sort according to some custom 
requirements. The problem is, that the less than function needs to be able 
to access some variables to determine the right sort order. My thought was 
to implement the compare function as a member function in my class, or 
something like that, but that results in a compiler error:

c:/Devel/Qt/4.4.0-beta1/include/QtCore/../../src/corelib/tools/qalgorithms.h:381: 
error: must use .* or ->* to call pointer-to-member function in `lessThan 
(...)'
c:/Devel/Qt/4.4.0-beta1/include/QtCore/../../src/corelib/tools/qalgorithms.h:206: 
instantiated from `void qSort(RandomAccessIterator, RandomAccessIterator, 
LessThan) [with RandomAccessIterator = QList<QDomElement>::iterator, 
LessThan = bool (PatentDataExtractor::*)(const QDomElement&, const 
QDomElement&)]'
src\patentdataextractor.cpp:57:   instantiated from here
c:/Devel/Qt/4.4.0-beta1/include/QtCore/../../src/corelib/tools/qalgorithms.h:386: 
error: must use .* or ->* to call pointer-to-member function in `lessThan 
(...)'
(...)

The documentation on qSort is rather sparse, and shows little examples. Is 
there another way to accomplish my special sort function? Could somebody 
point me to some information on how to accomplish this, or perhaps give a 
small code example on how to write the arguments to qSort if I want to use a 
member function?

Thanks!

André
 

--
 [ signature omitted ] 

Message 2 in thread

André Somers wrote:
> Using Qt 4.4 beta 1 on windows XP:
> 
> I would like to use qSort on a QList to sort according to some custom
> requirements. The problem is, that the less than function needs to be
> able to access some variables to determine the right sort order. My
> thought was to implement the compare function as a member function in my
> class, or something like that, but that results in a compiler error:

Can you post the offending code ?

-- 
 [ signature omitted ] 

Message 3 in thread


"Stephen Collyer" <scollyer@xxxxxxxxxxxxxxxx> wrote in message 
news:47DAA19E.8050707@xxxxxxxxxxxxxxxxxxx
> André Somers wrote:
>> Using Qt 4.4 beta 1 on windows XP:
>>
>> I would like to use qSort on a QList to sort according to some custom
>> requirements. The problem is, that the less than function needs to be
>> able to access some variables to determine the right sort order. My
>> thought was to implement the compare function as a member function in my
>> class, or something like that, but that results in a compiler error:
>
> Can you post the offending code ?

The code goes (something) like this:


QList<QDomElement> PatentDataExtractor::getSortedBiblioNodes() {
    //(...)

    QList<QDomElement> bel;

    //fill the list
    qSort(bel.begin(),bel.end(), PatentDataExtractor::biblioNodeLessThan);
    return bel;
}


bool PatentDataExtractor::biblioNodeLessThan(const QDomElement& e1, const 
QDomElement& e2) {
	//we always put the biblioentry of the document we were looking for on top
	if (e1.elementsByTagName("B111EP").at(0).toElement().text() == 
m_magicSortKey)
		return true;
	if (e2.elementsByTagName("B111EP").at(0).toElement().text() == 
m_magicSortKey)
		return false;

                // .... and so on
}


I hope this helps? I'm gratefull for any suggestions.

André 

--
 [ signature omitted ] 

Message 4 in thread

André Somers wrote:

> The code goes (something) like this:
> 
> 
> QList<QDomElement> PatentDataExtractor::getSortedBiblioNodes() {
>    //(...)
> 
>    QList<QDomElement> bel;
> 
>    //fill the list
>    qSort(bel.begin(),bel.end(), PatentDataExtractor::biblioNodeLessThan);
>    return bel;
> }

If biblioNodeLessThan() is a member function, I guess you will
have to use something like the Boost function library to produce
a function callback that is fully bound to the current object.
At the moment, you are passing what is essentially an offset
into an object; you need to give qSort a callback to a member
function associated with the current object. Take a look at
Boost function to see how to do that. You'll probably need to
use std::mem_ptr and std::bind1st, but I'd have to look up the
details to get the syntax right.

-- 
 [ signature omitted ] 

Message 5 in thread

Perhaps there is a detail I am missing, but wouldn't qsort "just work" if
you implemented the operator< for your class?

Evan Teran

Stephen Collyer wrote:

> André Somers wrote:
> 
>> The code goes (something) like this:
>> 
>> 
>> QList<QDomElement> PatentDataExtractor::getSortedBiblioNodes() {
>>    //(...)
>> 
>>    QList<QDomElement> bel;
>> 
>>    //fill the list
>>    qSort(bel.begin(),bel.end(), PatentDataExtractor::biblioNodeLessThan);
>>    return bel;
>> }
> 
> If biblioNodeLessThan() is a member function, I guess you will
> have to use something like the Boost function library to produce
> a function callback that is fully bound to the current object.
> At the moment, you are passing what is essentially an offset
> into an object; you need to give qSort a callback to a member
> function associated with the current object. Take a look at
> Boost function to see how to do that. You'll probably need to
> use std::mem_ptr and std::bind1st, but I'd have to look up the
> details to get the syntax right.
> 

--
 [ signature omitted ] 

Message 6 in thread


"André Somers" <andre@xxxxxxxxxxxxxxxx> wrote in message 
news:fre958$j8k$1@xxxxxxxxxxxxxxxx

>>> I would like to use qSort on a QList to sort according to some custom
>>> requirements. The problem is, that the less than function needs to be
>>> able to access some variables to determine the right sort order. My
>>> thought was to implement the compare function as a member function in my
>>> class, or something like that, but that results in a compiler error:

For now, I resorted to replacing the qSort call with a small, naive sorting 
routine of my own. This is not a big problem, since the list is not too long 
and sorting is not a big part of the time the code takes:

	int swapsMade = 0, cnt =0;
	int iterations = 0;
	cnt = bel.count();
	if (bel.count() > 1) {
		do {
			swapsMade = 0;
			for (int i=0; i < cnt - 1; i++) {
				if (biblioNodeLessThan(bel.at(i+1), bel.at(i))) {
					swapsMade ++;
					bel.swap(i, i+1);
					//qDebug() << "swap " << i << i+1;
				}
			}
			iterations++;
		} while (swapsMade != 0);
	}	qDebug() 
<< "processing order (sorting took" << iterations << "iterations)" ;

It just keeps on looping through the list untill there are no more swaps of 
neighbouring elements made.

I am still interested in how to get the qSort approach to work, but at least 
I can continue for now.

Thanks,

André
 

--
 [ signature omitted ] 

Message 7 in thread

André Somers wrote:
> [...]
> bool PatentDataExtractor::biblioNodeLessThan(const QDomElement& e1, 
> const QDomElement& e2) {
>     //we always put the biblioentry of the document we were looking 
> for on top
>     if (e1.elementsByTagName("B111EP").at(0).toElement().text() == 
> m_magicSortKey)
>         return true;
>     if (e2.elementsByTagName("B111EP").at(0).toElement().text() == 
> m_magicSortKey)
>         return false;
>
>                // .... and so on
> }
> [...]
How about making the method a non-member friend of the class? Have not 
tried it, though.

Regards

Kai Koehne

--
 [ signature omitted ]