c++ - के साथ एक QMap पर Iterating




qt c++11 (5)

मेरे पास एक QMap ऑब्जेक्ट है और मैं अपनी सामग्री को एक फ़ाइल में लिखने की कोशिश कर रहा हूं।

QMap<QString, QString> extensions;
//.. 

for(auto e : extensions)
{
  fout << e.first << "," << e.second << '\n';
}  

मुझे क्यों मिलता है: error: 'class QString' has no member named 'first' nor 'second'

क्या e QPair टाइप नहीं है?


QMap :: iterator कुंजी () और मान () का उपयोग करता है - जिसे क्यूटी 4.8 के लिए प्रलेखन में आसानी से पाया जा सकता है या Qt-5 के लिए प्रलेखन

संपादित करें:

लूप के लिए एक श्रेणी-आधारित कोड इसी तरह के कोड उत्पन्न करता है ( सीपीपी संदर्भ देखें):

{
    for (auto __begin = extensions.begin(), __end = extensions.end();
            __begin != __end; ++__begin) {
        auto e = *__begin; // <--- this is QMap::iterator::operator*()
        fout << e.first << "," << e.second << '\n';
    }
} 

QMap :: iterator :: iterator * () QMap :: iterator :: value () के बराबर है, और एक जोड़ी नहीं देता है।

इसे लिखने का सबसे अच्छा तरीका लूप के लिए सीमा-आधारित है:

auto end = extensions.cend();
for (auto it = extensions.cbegin(); it != end; ++it)
{
    std::cout << qPrintable(it.key()) << "," << qPrintable(it.value());
}

अनुकूलन में रूचि रखने वाले लोगों के लिए, मैंने कई दृष्टिकोणों की कोशिश की है, कुछ माइक्रो बेंचमार्क किए हैं, और मैं निष्कर्ष निकाल सकता हूं कि एसटीएल शैली दृष्टिकोण काफी तेज है

मैंने इन विधियों के साथ पूर्णांक जोड़ने का प्रयास किया है:

  • QMap :: मूल्यों ()
  • जावा स्टाइल इटरेटर (जैसा कि प्रलेखन में सलाह दी गई है)
  • एसटीएल स्टाइल इटरेटर (जैसा कि दस्तावेज में भी सलाह दी गई है)

और मैंने इसे QList / QVector के संक्षिप्त पूर्णांक के साथ तुलना की है

परिणाम:

Reference vector :   244  ms
Reference list :     1239  ms

QMap::values() :     6504  ms
Java style iterator :    6199  ms
STL style iterator :     2343  ms

रुचि रखने वालों के लिए कोड:

#include <QDateTime>
#include <QMap>
#include <QVector>
#include <QList>
#include <QDebug>

void testQMap(){
    QMap<int, int> map;
    QVector<int> vec;
    QList<int> list;

    int nbIterations = 100;
    int size = 1000000;
    volatile int sum = 0;

    for(int i = 0; i<size; ++i){
        int randomInt = qrand()%128;
        map[i] = randomInt;
        vec.append(randomInt);
        list.append(randomInt);
    }


    // Rererence vector/list
    qint64 start = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        for(int j : vec){
            sum += j;
        }
    }
    qint64 end = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Reference vector : \t" << (end-start) << " ms";

    qint64 startList = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        for(int j : list){
            sum += j;
        }
    }
    qint64 endList = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Reference list : \t" << (endList-startList) << " ms";

    // QMap::values()
    qint64 start0 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QList<int> values = map.values();
        for(int k : values){
            sum += k;
        }
    }
    qint64 end0 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "QMap::values() : \t" << (end0-start0) << " ms";


    // Java style iterator
    qint64 start1 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QMapIterator<int, int> it(map);
        while (it.hasNext()) {
            it.next();
            sum += it.value();
        }
    }
    qint64 end1 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Java style iterator : \t" << (end1-start1) << " ms";


    // STL style iterator
    qint64 start2 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QMap<int, int>::const_iterator it = map.constBegin();
        auto end = map.constEnd();
        while (it != end) {
            sum += it.value();
            ++it;
        }
    }
    qint64 end2 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "STL style iterator : \t" << (end2-start2) << " ms";


    qint64 start3 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        auto end = map.cend();
        for (auto it = map.cbegin(); it != end; ++it)
        {
            sum += it.value();
        }
    }
    qint64 end3 = QDateTime::currentMSecsSinceEpoch();

    qDebug() << "STL style iterator v2 : \t" << (end3-start3) << " ms";
}

जुलाई 2017 संपादित करें: मैंने अपने नए लैपटॉप (क्यूटी 5.9, i7-7560U) पर फिर से यह कोड चलाया और कुछ दिलचस्प बदलाव किए

Reference vector :   155  ms 
Reference list :     157  ms
QMap::values():      1874  ms 
Java style iterator: 1156  ms 
STL style iterator:  1143  ms

एसटीएल शैली और जावा शैली के इस बेंचमार्क में बहुत ही समान प्रदर्शन हैं


मैंने अपना खुद का परिणाम प्राप्त करने के लिए ऐसा कुछ किया। बस अगर किसी को चाबियाँ और मूल्यों को अलग से चाहिए।

{
   QMap<int,string> map; 

   map.insert(1,"One");
   map.insert(2,"Two");
   map.insert(3,"Three");
   map.insert(4,"Four");   

   fout<<"Values in QMap 'map' are:"<<endl;
   foreach(string str,map)
   {
     cout<<str<<endl;
   };


   fout<<"Keys in QMap 'map' are:"<<endl;
   foreach(int key,map.keys())
   {
     cout<<key<<endl;
   }; 
}  

यदि आप एसटीएल शैली को first और second साथ चाहते हैं, तो ऐसा करें:

for(auto e : extensions.toStdMap())
{
  fout << e.first << "," << e.second << '\n';
}

यदि आप क्यूटी ऑफर का उपयोग करना चाहते हैं, तो यह करें:

for(auto e : extensions.keys())
{
  fout << e << "," << extensions.value(e) << '\n';
}

क्यूमैप डॉक्स से एक और सुविधाजनक तरीका। यह कुंजी और मूल्य (जावा-स्टाइल इटरेटर) तक स्पष्ट पहुंच की अनुमति देता है:

QMap<QString, QString> extensions;
// ... fill extensions
QMapIterator<QString, QString> i(extensions);
while (i.hasNext()) {
    i.next();
    qDebug() << i.key() << ": " << i.value();
}

यदि आप ओवरराइट करने में सक्षम होना चाहते हैं, QMutableMapIterator इसके बजाय QMutableMapIterator उपयोग करें।

एक और सुविधाजनक Qt विधि है, यदि आप केवल कुंजियों के बिना मूल्यों को पढ़ने में रुचि रखते हैं ( Qt foreach और c ++ 11 का उपयोग कर):

QMap<QString, QString> extensions;
// ... fill extensions
foreach (const auto& value, extensions)
{
    // to stuff with value
}






qmap