How to convert QList to QSet in Qt 6
Asked Answered
P

2

6

I am porting my application to Qt 6 and as I am reading documentation I see that classes are cleaned up a lot, QList and QVector are unified, QStringList is now alias to QList<QString> and so on.

But now this gave me one problem.

In my code (which is Qt 5) I am converting QStringList to QSet to eliminate duplicates from the list. I went through new documentation but I haven't seen a way to convert QList to QSet in Qt 6.

So how do you convert QList to QSet? Or it is not possible and I will need to write a helper function for removing duplicates?

EDIT: I am using Qt 6.0.1.

Pytlik answered 9/2, 2021 at 16:42 Comment(0)
D
6

I must admit that I'm still on Qt5.

However, QList and QSet remind me strong to std::list and std::set. For the latter, there was already another (and more flexible) way to achieve such things: using construction with iterators. A short check in the Qt6 doc. convinced me, this should work in the Qt classes as well:

QSet::QSet(InputIterator first, InputIterator last)

Constructs a set with the contents in the iterator range [first, last).

The value type of InputIterator must be convertible to T.

Note: If the range [first, last) contains duplicate elements, the first one is retained.

This function was introduced in Qt 5.14.

where first is set with

QList::iterator QList::begin()

Returns an STL-style iterator pointing to the first item in the list.

and last with

QList::iterator QList::end()

Returns an STL-style iterator pointing to the imaginary item after the last item in the list.

How this should look like when put together:

QList<QString> aList;
// populate list
QSet<QString> aSet(aList.begin(), aList.end());

OP noted that the Qt-5 doc. already contained a hint concerning this:

QSet QList::toSet() const

Note: Since Qt 5.14, range constructors are available for Qt's generic container classes and should be used in place of this method.

OP also mentioned a convenience wrapper:

template <typename T>
QSet<T> QListToQSet(const QList<T>& qlist)
{
  return QSet<T> (qlist.constBegin(), qlist.constEnd());
}

applied to the above sample:

QList<QString> aList;
// populate list
QSet<QString> aSet = QListToQSet(aList);

A more general conversion facility would probably be something like this:

template <typename T, template<typename> typename C>
QSet<T> toQSet(const C<T> &container)
{
  return QSet<T>(container.begin(), container.end());
}

which would work even with matching std containers as well:

std::vector<QString> aVec = { "Hello", "World", "Hello" };
QSet<QString> aSet = toSet(aVec);
Diacritic answered 10/2, 2021 at 9:49 Comment(0)
B
-1

you are right, see in the code or the doc that QStringList is a child of QList

class QStringList : public QList<QString>
{

so you can call QSet toSet() const; directly since the method is public.

with this, you can unzip directly the content of the QStringlist to a qset

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

    QString str = "one,two,three,four,one";
    QStringList strlt = str.split(QChar(','));

    const QSet<QString> strVe = strlt.toSet();
    qDebug() << strVe;

    return a.exec();
}
Battalion answered 9/2, 2021 at 16:56 Comment(1)
QStringList doesn't have toSet on it any more, unfortunately.Duodiode

© 2022 - 2025 — McMap. All rights reserved.