[Interest] How to make the QString "10" behind "9" in QMap's key order

Konstantin Tokarev annulen at yandex.ru
Mon Jan 8 20:29:07 CET 2018



> On Mon, Jan 8, 2018 at 5:25 PM, Konstantin Tokarev <annulen at yandex.ru> wrote:
> 
>> 08.01.2018, 14:34, "Carel Combrink" <carel.combrink at gmail.com>:
>>
>>> Hi Mark,
>>
>>>
>>
>>> How would one use QCollatorSortKey for this type of application?
>>
>> Note that you should use QCollatorSortKey if and only if you are going to sort same values many times, or use binary search in the sorted vector. Otherwise use QCollator.
> 
> That is not true!
> 
> I had benchmarked this years ago and using QCollator directly is _always_ the slowest path.
> I had a whole blogpost about that, but that blog went offline... The code is still somewhere, but i'm very sure that using QCollator directly is never the fastest path in terms of performance, not even for a few entries. In terms of ease of use it is the easiest one :)

That's interesting. I thought that QCollatorSortKey is an intermediate result of QCollator's comparison algorithm which is serialized in reusable form, so in theory sort key should not provide better performance if you do one comparison and throw it away

http://userguide.icu-project.org/collation/architecture#TOC-Sort-Keys

> 
>>>
>>
>>> Unfortunately I have to say that the Qt documentation on this class is not as descriptive compared to other classes.
>>
>>>
>>
>>> Regards,
>>
>>> Carel
>>
>>>
>>
>>> On Mon, Jan 8, 2018 at 11:50 AM, Mark Gaiser <markg85 at gmail.com> wrote:
>>
>>>> On Mon, Jan 8, 2018 at 4:18 AM, jack ma <assangema at gmail.com> wrote:
>>
>>>>> Thanks all of you, seems that std::sort + QCollator is a good way
>>
>>>>>
>>
>>>>> 2018-01-07 18:47 GMT+08:00 Konstantin Tokarev <annulen at yandex.ru>:
>>
>>>>>
>>
>>>>>>> Hi,
>>
>>>>>>>
>>
>>>>>>> you need a "lessThan"-function, tailored for your needs. An
>>
>>>>>>> example from me is this:
>>
>>>>>>>
>>
>>>>>>> bool Person::lessThanFamilyFirst(QSharedPointer<Person>
>>
>>>>>>> p1, QSharedPointer<Person>
>>
>>>>>>> p2)
>>
>>>>>>>
>>
>>>>>>> {
>>
>>>>>>>
>>
>>>>>>> return (QString::localeAwareCompare(p1->familyName(),p2->familyName())<0)
>>
>>>>>>>
>>
>>>>>>> || (( p1->familyName() == p2->familyName())
>>
>>>>>>>
>>
>>>>>>> && (QString::localeAwareCompare(p1->firstName(),p2->firstName())<0));
>>
>>>>>>>
>>
>>>>>>> }
>>
>>>>>>>
>>
>>>>>>> Now you can pass this as a functor to a sort method like this:
>>
>>>>>>>
>>
>>>>>>> std::stable_sort(pupils.begin(), pupils.end(), Person::lessThanFamilyFirst);
>>
>>>>>>
>>
>>>>>> FWIW, if this is not a list displayed in UI, or other place where preserving order of
>>
>>>>>> equal elements matters, you should consider std::sort
>>
>>>>>>
>>
>>>>>>>
>>
>>>>>>> Please notice, that there are no () when calling the lessThan functor.
>>
>>>>>>
>>
>>>>>> Original question was dealing with QMap. While sorted vector-like container can replace
>>
>>>>>> map (there is even convenience wrapper flat_map in Boost, which allows to work with
>>
>>>>>> sorted array just like it was a "true" map), it doesn't always fit, e.g. inserts in such
>>
>>>>>> "flat map" are very expensive.
>>
>>>>>>
>>
>>>>>> So, you can just replace QMap with std::map and pass your comparator, e.g.
>>
>>>>>>
>>
>>>>>> auto comparator = [](const QString &a, const QString &b) -> bool {
>>
>>>>>> // Your comparison function here
>>
>>>>>> };
>>
>>>>>> std::map<QString, QGraphicsItem *, decltype(comparator)> myMap(comparator);
>>
>>>>>>
>>
>>>>>> See [1] for more examples.
>>
>>>>>>
>>
>>>>>> Yet another approach is to use your own type as a key of QMap instead of QString,
>>
>>>>>> and create desired operator< for it. This has a downside that your access to internal
>>
>>>>>> QString will be more complicated, and you'll have to invent different key type each time
>>
>>>>>> you want to change comparator.
>>
>>>>>>
>>
>>>>>> And, last but not least: you probably want to know *how* to write comparator for your
>>
>>>>>> particular sorting order. You can do this with QCollator, see [2].
>>
>>>>>>
>>
>>>>>> [1] http://en.cppreference.com/w/cpp/container/map/map
>>
>>>>>> [2] https://forum.qt.io/topic/68910/natural-sort-using-qcollator/2
>>
>>>>>>
>>
>>>>>>>
>>
>>>>>>> HTH
>>
>>>>>>> Sebastian
>>
>>>>>>>
>>
>>>>>>> Am 07.01.2018 um 09:01 schrieb jack ma:
>>
>>>>>>>
>>
>>>>>>>> Hi,
>>
>>>>>>>>
>>
>>>>>>>> there is a QMap<QString,QGraphicsItem *> type, then
>>
>>>>>>>> insert values with:
>>
>>>>>>>>
>>
>>>>>>>> type.insert("U1",nullptr),
>>
>>>>>>>>
>>
>>>>>>>> type.insert("U2",nullptr),
>>
>>>>>>>>
>>
>>>>>>>> …………
>>
>>>>>>>>
>>
>>>>>>>> type.insert("U9",nullptr),
>>
>>>>>>>>
>>
>>>>>>>> type.insert("U10",nullptr),
>>
>>>>>>>>
>>
>>>>>>>> I want get the values follow the order of U1, U2 ... U10,
>>
>>>>>>>> but the default order is U1, U10 ,……U9
>>
>>>>>>>>
>>
>>>>>>>> I know this is a common string sorting problem, but I do
>>
>>>>>>>> not know how to solve it well.
>>
>>>>>>>>
>>
>>>>>>>> Any suggestions are very grateful !
>>
>>>>>>>>
>>
>>>>>>>> Thanks.
>>
>>>>>>>>
>>
>>>>>>>> _______________________________________________
>>
>>>>>>>> Interest mailing list
>>
>>>>>>>> Interest at qt-project.org
>>
>>>>>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>>>>>>>
>>
>>>>>>> --
>>
>>>>>>> http://www.classintouch.de - Tablet-Software für Lehrer
>>
>>>>>> --
>>
>>>>>> Regards,
>>
>>>>>> Konstantin
>>
>>>>>> _______________________________________________
>>
>>>>>> Interest mailing list
>>
>>>>>> Interest at qt-project.org
>>
>>>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>>>>>
>>
>>>>> _______________________________________________
>>
>>>>> Interest mailing list
>>
>>>>> Interest at qt-project.org
>>
>>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>>>> Hi,
>>
>>>>
>>
>>>> You might want to look into std::map[1] as well. It allows setting a compare function, QMap doesn't.
>>
>>>> Going that route is most likely more efficient as your inserts will be sorted, no need to do std::sort afterwards.
>>
>>>>
>>
>>>> You still would have to use QCollator. Note that you can just use QCollator in the compare method which will work just fine, but is not the performant way to go.
>>
>>>> The most performant way (i know of) is by using QCollatorSortKey[2].
>>
>>>>
>>
>>>> [1] http://en.cppreference.com/w/cpp/container/map/map
>>
>>>> [2] http://doc.qt.io/qt-5/qcollatorsortkey.html
>>
>>>>
>>
>>>> _______________________________________________
>>
>>>> Interest mailing list
>>
>>>> Interest at qt-project.org
>>
>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>>> ,
>>
>>>
>>
>>> _______________________________________________
>>
>>> Interest mailing list
>>
>>> Interest at qt-project.org
>>
>>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>> --
>>
>> Regards,
>>
>> Konstantin
-- 
Regards,
Konstantin



More information about the Interest mailing list