Discussion:
[Interest] Best practice for sorting multiple (connected) QLists
Joshua Grauman
2013-11-19 20:26:44 UTC
Permalink
I fairly often find myself wanting to sort a bit of data. Imagine I have a
few QList<int>'s a QStringList's and that they correspond like a database
table so that I always append to all the lists together with data for one
row. Something like:

QList<int> age, height;
QStringList firstname, lastname;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
}

Now what if I want to sort all that data, (say by age) so that I can print
out all the first and last names in order according to age.

I've tried different ways of doing this, but they all seem a bit
contrived. The best I've come up with is to have another QMap<int, int>
that maps the sorting order to the indices like:

QList<int> age, height;
QStringList firstname, lastname;
QMap<int, int> order;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
order[age.last()] = age.size()-1;
}

QList<int> orderedIndices = order.values();

for(int i=0; i<orderedIndices.size(); i++)
{
print(firstname[orderedIndices[i]], lastname[orderedIndices[i]]);
}

It's not too bad. I'm not worried about performance, most of the time
these are just small amounts of data that don't warrant creating a new
class to handle, or creating a database for. I'm just wondering if anyone
has a cleaner way of handling this? What do you do for these types of
situations?

Josh
a***@familiesomers.nl
2013-11-19 20:41:18 UTC
Permalink
Post by Joshua Grauman
I fairly often find myself wanting to sort a bit of data. Imagine I have a
few QList<int>'s a QStringList's and that they correspond like a database
table so that I always append to all the lists together with data for one
QList<int> age, height;
QStringList firstname, lastname;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
}
Now what if I want to sort all that data, (say by age) so that I can print
out all the first and last names in order according to age.
I think your problem is in your data structure. Instead of using
separate containers for each of the fields, you should use a single
container with all of the fields:

struct Person
{
int age;
int height;
QString firstName;
QString lastName;
}

QList<Person> persons;
while(data)
{
Person person;
person.age = getData1();
person.height = getData2();
person.firstName = getData3();
person.lastName = getData4();
persons.append(person);
}

Now, you can easily sort the persons list itself by using qSort with a
comparison function for the field you want to sort on, or keep track of
the order by using a QMap<key, int> using the index into the persons
list as the value of your map.

Alternatively, look into Boost.MultiIndex.

André
Post by Joshua Grauman
I've tried different ways of doing this, but they all seem a bit
contrived. The best I've come up with is to have another QMap<int, int>
QList<int> age, height;
QStringList firstname, lastname;
QMap<int, int> order;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
order[age.last()] = age.size()-1;
}
QList<int> orderedIndices = order.values();
for(int i=0; i<orderedIndices.size(); i++)
{
print(firstname[orderedIndices[i]], lastname[orderedIndices[i]]);
}
It's not too bad. I'm not worried about performance, most of the time
these are just small amounts of data that don't warrant creating a new
class to handle, or creating a database for. I'm just wondering if anyone
has a cleaner way of handling this? What do you do for these types of
situations?
Josh
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Guido Seifert
2013-11-19 21:15:05 UTC
Permalink
Post by a***@familiesomers.nl
I think your problem is in your data structure. Instead of using
separate containers for each of the fields, you should use a single
Maybe. Another nice way is to drop the QList at all and use an in-memory
sqlite database. Easily searched and sorted in any way one could wish.

Guido
André Somers
2013-11-20 07:07:08 UTC
Permalink
Post by Guido Seifert
Post by a***@familiesomers.nl
I think your problem is in your data structure. Instead of using
separate containers for each of the fields, you should use a single
Maybe. Another nice way is to drop the QList at all and use an in-memory
sqlite database. Easily searched and sorted in any way one could wish.
Downsides: cluncky API and not type safe. Seems like a lot of overhead
for such a simple task.

André
Guido Seifert
2013-11-20 19:37:10 UTC
Permalink
Post by André Somers
Downsides: cluncky API and not type safe. Seems like a lot of overhead
for such a simple task.
Type safety: Ok.
Clunky API? -> Qt API.
Lot of overhead? If you have Qt installed anyways, it does not matter.
And if you have used it before and just need to copy/paste the code
and change the sql part a bit... IMHO less overhead than fiddling with
lists. Especially since for such a use case it's only a few lines
trivial sql.


But of course, mostly a matter of taste.

Guido

Constantin Makshin
2013-11-20 03:41:41 UTC
Permalink
Another advantages of this approach are more efficient memory utilisation
(less storage and [re]allocation overhead) somewhat better cache locality
because all fields related to a particular person will be close to each
other in memory instead of being spread all over the place ("somewhat
better" because QString-s and similar classes will need indirections to
access their contents anyway).

I personally would recommend not to use separate lists for closely-related
data unless that's *really* neccessary.
Post by a***@familiesomers.nl
Post by Joshua Grauman
I fairly often find myself wanting to sort a bit of data. Imagine I have a
few QList<int>'s a QStringList's and that they correspond like a database
table so that I always append to all the lists together with data for one
QList<int> age, height;
QStringList firstname, lastname;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
}
Now what if I want to sort all that data, (say by age) so that I can print
out all the first and last names in order according to age.
I think your problem is in your data structure. Instead of using
separate containers for each of the fields, you should use a single
struct Person
{
int age;
int height;
QString firstName;
QString lastName;
}
QList<Person> persons;
while(data)
{
Person person;
person.age = getData1();
person.height = getData2();
person.firstName = getData3();
person.lastName = getData4();
persons.append(person);
}
Now, you can easily sort the persons list itself by using qSort with a
comparison function for the field you want to sort on, or keep track of
the order by using a QMap<key, int> using the index into the persons
list as the value of your map.
Alternatively, look into Boost.MultiIndex.
André
Post by Joshua Grauman
I've tried different ways of doing this, but they all seem a bit
contrived. The best I've come up with is to have another QMap<int, int>
QList<int> age, height;
QStringList firstname, lastname;
QMap<int, int> order;
while(data)
{
age.append(getData1());
height.append(getData2());
firstname.append(getData3());
lastname.append(getData4());
order[age.last()] = age.size()-1;
}
QList<int> orderedIndices = order.values();
for(int i=0; i<orderedIndices.size(); i++)
{
print(firstname[orderedIndices[i]], lastname[orderedIndices[i]]);
}
It's not too bad. I'm not worried about performance, most of the time
these are just small amounts of data that don't warrant creating a new
class to handle, or creating a database for. I'm just wondering if anyone
has a cleaner way of handling this? What do you do for these types of
situations?
Josh
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Loading...