Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Unsorted QVector
QtWS25 Last Chance

Unsorted QVector

Scheduled Pinned Locked Moved Solved General and Desktop
qvectorsorting
11 Posts 7 Posters 3.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Buckwheat
    wrote on 5 Apr 2018, 14:17 last edited by
    #2

    Hi @sayan275

    Unfortunately because of the standard string compare functions you get the behavior you are seeing. The easiest way to solve this in an ideal sense is to prepend '0' to all the numbers. This is not practical or desirable. Instead, what you will need to do is write your own smart compare function that has some knowledge of your file names.

    Luckily, QVector, QList, and QMap can be used like the C++Library std::vector, std::list, and std::map.

    Here is what I am referring to:

    int my_comparator (const QString& lhs, const QString& rhs)
    {
    // Write some smart stuff to compare the files with numeric ordering
    if (lhs < rhs) return -1;
    else if (lhs > rhs) return 1;
    else return 0;
    }

    ... more code here ...

    std::sort (my_vector.begin (), my_vector.end (), my_comparator);

    Unfortunately, there is no easy way to do this except your custom function. Luckily everything you need is available. I would suggest you look online for a good test comparator that does what you want. Here is a decent article you can read about human sorting.

    https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/

    Dave Fileccia

    1 Reply Last reply
    4
    • G Offline
      G Offline
      Gojir4
      wrote on 5 Apr 2018, 14:18 last edited by Gojir4 4 May 2018, 14:26
      #3

      Hello,

      This is because you are sorting strings, so 10, 100, etc.. comes before 2 in alphabet order.
      You have to convert them to numbers to sort them correctly.

      You can use std::sort() with custom "Compare" method for that.

      using lambda :

      std::sort(vector.begin(), vector.end(), [](const QString& a, const QString b) { 
          bool okA, okB;
          int ia = QFileInfo(a).baseName().toUint(&okA);
          int ib = QFileInfo(a).baseName().toUint(&okB);
         if(!okA || !okB)
              return a < b;
          return ia < ib; 
      });
      

      without lambda:

      bool compareNumberFileName(const QString& a, const QString b) { 
          bool okA, okB;
          int ia = QFileInfo(a).baseName().toUint(&okA);
          int ib = QFileInfo(a).baseName().toUint(&okB);
         if(!okA || !okB)
              return a < b;
          return ia < ib; 
      }
      
      std::sort(vector.begin(), vector.end(), compareNumberFileName);
      

      In case you are using always the same folder, you can store only numbers corresponding to file names in QVector<uint> and then construct the file name when it's necessary.

      S 1 Reply Last reply 6 Apr 2018, 04:29
      5
      • M Offline
        M Offline
        mrjj
        Lifetime Qt Champion
        wrote on 5 Apr 2018, 15:16 last edited by
        #4

        Hi
        I was wondering if QStringList would just work if the goal is to just have them in the same order as inserted ?

        G S 2 Replies Last reply 5 Apr 2018, 15:41
        4
        • M mrjj
          5 Apr 2018, 15:16

          Hi
          I was wondering if QStringList would just work if the goal is to just have them in the same order as inserted ?

          G Offline
          G Offline
          Gojir4
          wrote on 5 Apr 2018, 15:41 last edited by
          #5

          @mrjj Yes it should. QList<> keep items in the order they are inserted. This is also the case of QVector<>.

          1 Reply Last reply
          3
          • M mrjj
            5 Apr 2018, 15:16

            Hi
            I was wondering if QStringList would just work if the goal is to just have them in the same order as inserted ?

            S Offline
            S Offline
            sayan275
            wrote on 6 Apr 2018, 03:46 last edited by
            #6

            @mrjj It's the same with QStringList. Actually the problem is with the container only which contains the qstring paths as sorted,
            "./zThumbnail/1004.jpeg"
            "./zThumbnail/1005.jpeg"
            "./zThumbnail/1006.jpeg"
            "./zThumbnail/1007.jpeg"
            "./zThumbnail/1008.jpeg"
            "./zThumbnail/1009.jpeg"
            "./zThumbnail/101.jpeg"
            "./zThumbnail/1010.jpeg"
            "./zThumbnail/1011.jpeg"
            "./zThumbnail/1012.jpeg"
            "./zThumbnail/1013.jpeg"

            QFileInfoList filelistinfo = dir.entryInfoList();
            foreach (const QFileInfo &fileinfo, filelistinfo) {
            imagePath.push_back(fileinfo.absoluteFilePath());
            qDebug() << fileinfo.absoluteFilePath();
            }

            A 1 Reply Last reply 6 Apr 2018, 05:00
            0
            • G Gojir4
              5 Apr 2018, 14:18

              Hello,

              This is because you are sorting strings, so 10, 100, etc.. comes before 2 in alphabet order.
              You have to convert them to numbers to sort them correctly.

              You can use std::sort() with custom "Compare" method for that.

              using lambda :

              std::sort(vector.begin(), vector.end(), [](const QString& a, const QString b) { 
                  bool okA, okB;
                  int ia = QFileInfo(a).baseName().toUint(&okA);
                  int ib = QFileInfo(a).baseName().toUint(&okB);
                 if(!okA || !okB)
                      return a < b;
                  return ia < ib; 
              });
              

              without lambda:

              bool compareNumberFileName(const QString& a, const QString b) { 
                  bool okA, okB;
                  int ia = QFileInfo(a).baseName().toUint(&okA);
                  int ib = QFileInfo(a).baseName().toUint(&okB);
                 if(!okA || !okB)
                      return a < b;
                  return ia < ib; 
              }
              
              std::sort(vector.begin(), vector.end(), compareNumberFileName);
              

              In case you are using always the same folder, you can store only numbers corresponding to file names in QVector<uint> and then construct the file name when it's necessary.

              S Offline
              S Offline
              sayan275
              wrote on 6 Apr 2018, 04:29 last edited by
              #7

              @Gojir4 Thanks for the suggestion.
              I constructed the filepaths.

              D 1 Reply Last reply 6 Apr 2018, 05:31
              0
              • S sayan275
                6 Apr 2018, 03:46

                @mrjj It's the same with QStringList. Actually the problem is with the container only which contains the qstring paths as sorted,
                "./zThumbnail/1004.jpeg"
                "./zThumbnail/1005.jpeg"
                "./zThumbnail/1006.jpeg"
                "./zThumbnail/1007.jpeg"
                "./zThumbnail/1008.jpeg"
                "./zThumbnail/1009.jpeg"
                "./zThumbnail/101.jpeg"
                "./zThumbnail/1010.jpeg"
                "./zThumbnail/1011.jpeg"
                "./zThumbnail/1012.jpeg"
                "./zThumbnail/1013.jpeg"

                QFileInfoList filelistinfo = dir.entryInfoList();
                foreach (const QFileInfo &fileinfo, filelistinfo) {
                imagePath.push_back(fileinfo.absoluteFilePath());
                qDebug() << fileinfo.absoluteFilePath();
                }

                A Offline
                A Offline
                aha_1980
                Lifetime Qt Champion
                wrote on 6 Apr 2018, 05:00 last edited by
                #8

                @sayan275 neither QVector nor QStringList are sorted!

                they are just containers that can be sorted. but if you append or push_back, than new items appear at the end.

                so you will have to sort the list yourself, as already suggested.

                Qt has to stay free or it will die.

                1 Reply Last reply
                4
                • S sayan275
                  6 Apr 2018, 04:29

                  @Gojir4 Thanks for the suggestion.
                  I constructed the filepaths.

                  D Offline
                  D Offline
                  Devopia53
                  wrote on 6 Apr 2018, 05:31 last edited by Devopia53 4 Jun 2018, 08:12
                  #9

                  @sayan275

                  With QMap, the items are always sorted by key.

                  You can also use the QMap. like this:

                  QFileInfoList filelistinfo = dir.entryInfoList(QStringList() << "*.jpeg");
                  QMap<int, QString> map;
                  for (const QFileInfo &fileinfo : qAsConst(filelistinfo))
                      map[fileinfo.baseName().toInt()] = fileinfo.absoluteFilePath();
                  for (QString value : qAsConst(map))
                      qDebug() << value;
                  
                  1 Reply Last reply
                  2
                  • J Offline
                    J Offline
                    J.Hilk
                    Moderators
                    wrote on 6 Apr 2018, 05:34 last edited by
                    #10

                    To add my 2 cents,
                    you could sort twice, first along the string length than, in blocks, along the string itself.


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      sayan275
                      wrote on 12 Apr 2018, 06:00 last edited by
                      #11

                      I got it done by the below code

                      QFileInfoList filelistinfo = dir.entryInfoList();
                      for(const QFileInfo &fileinfo: filelistinfo) 
                          imagePath.push_back(fileinfo.absoluteFilePath());
                      
                      std::sort(imagePath.begin(), imagePath.end(),
                                [](const QString & a, const QString & b) -> bool
                      {
                          return QFileInfo(a).baseName().toInt() < QFileInfo(b).baseName().toInt();
                      });
                      
                      qDebug()<<imagePath;
                      
                      1 Reply Last reply
                      0

                      11/11

                      12 Apr 2018, 06:00

                      • Login

                      • Login or register to search.
                      11 out of 11
                      • First post
                        11/11
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved