Sortierproblem mit Maps und Vektoren



  • Probiers mal mit stable_sort() anstatt sort().



  • Nein, das hilft nicht. Jetzt wird zuerstmal diese Zeile

    std::__inplace_stable_sort(__first, __last, __comp);
    

    in stl_algo.h angemeckert. Der gesamte Fehler unterscheidet sich nicht viel von dem vorherigen.



  • Hast du die Klasse Sorter an dein const string angepasst?

    class Sorter
    {
    public:
        bool operator ()(const map<const string, int>::const_iterator &lhs, const map<const string, int>::const_iterator &rhs)    // direkt noch die Parameter const gemacht
        {
            return lhs->second <= rhs->second;
        }
    };
    


  • Eine map wird nicht über std::sort sortiert. Das erfordert RandomAccessItertoren und die gibt es für die map nicht.
    Eine map sortiert sich selbst beim Einfügen.

    Du musst beim Erzeugen der Map einen Comparator übergeben, der dein Vergleichskriterium enthält:

    class Comp {
      public:
        bool operator( const string& s1, const std::string s2) const 
        {
           return s1 > s2; // oder was immer Du willst  
        }
    };
    
    void x()
    {
       map<string, int, Comp> myMap;
      //   myMap.insert <- fügt es an der Stelle gemäß obigen Kriterium ein
    }
    

    }



  • Ich habe erst vor kurzem mit C++ angefangen und ich bin noch nicht in der Lage einen "Funktor" (von dem ich bis jetzt noch nie was gehört habe) anzupassen 😉
    Aber mit deiner neuen Version funktioniert es genau so wenig.



  • Floele schrieb:

    Das Problem ist nun, dass sich Maps (meines Wissens) nicht sortieren lassen bzw. automatisch sortiert werden - nur falsch herum.

    Das kommt ganz darauf an - du kannst der Map als Template-parameter eine Comparator-Klasse mitgeben. Die ist per default std::less<Key>. Wenn du stattdessen std::greater<Key> (in deinem Fall also std::greaterstd::string) einsetzt, wird sie genau andersrum sortiert. Da man den Comparator allerdings nur einmal angeben kann, lohnt sich das nur, wenn es okay ist, dass die Map IMMER so sortiert ist. (evtl. könnte man sonst per std::copy() die Elemente einer mit less<> sortierten map in eine mit greter<> sortierten map kopieren...)



  • @niemand

    63 (...) expected identifier before '(' token
    

    in dieser Zeile:

    bool operator( const string& s1, const std::string s2) const
    

    Habe bisher mit Operatorüberladungen (oder was immer das ist) nicht gearbeitet, also wäre es schon schön wenn du mir einen Code geben könntest der fehlerfrei kompliert. Bis ich in C++ soweit bin wird es noch ein bisschen dauern.



  • @pumuckl

    So ist es im Moment perfekt, also vielen Dank 🙂



  • Moment, in Deinem ersten Post steht, dass Du nach int sortieren willst. Dann wäre die map falsch. Die map sortiert immer nach dem ersten Typ. Hier ein ausprobiertes Beispiel. Sortiert die Zahlen absteigend. Hoffe, das hilft weiter.

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    class Comp
    {
    public:
       bool operator()( const int i1, const int i2) const
       {
          return i1 > i2;
       }
    };
    
    int main()
    {
       map<int, string, Comp> x;
       x.insert( make_pair( 2, string( "Hallo")));
       x.insert( make_pair( 5, string( "Test")));
       x.insert( make_pair( 1, string( "Welt")));
       x.insert( make_pair( 3, string( "C++")));
    
       map<int, string, Comp>::const_iterator it = x.begin();
       map<int, string, Comp>::const_iterator const end = x.end();
       for( ; it != end; ++it) {
          cout << it->first << " " << it->second << endl;
       }
    
    }
    


  • Haha, das habe ich auch grade gemerkt (mein erster Test sah so aus als wenn das wäre was ich brauche - war es aber doch nicht) 😃
    Gucke mir deinen Code direkt mal an.



  • Wenn du nach value sortieren willst wird dir nichts anderes übrig bleiben als vor dem sortieren in einen vector umzukopieren.

    #include <iostream>
    #include <vector>
    #include <map>
    #include <algorithm>
    
    typedef std::pair<std::string, int> string_int_pair;
    
    class Sorter
    {
    public:
        bool operator ()(const string_int_pair &lhs, const string_int_pair &rhs) const {
            return lhs.second < rhs.second;
        }
    };
    
    int main() {
    
       std::map<std::string, int> m;
       std::vector<string_int_pair> v;
       m.insert(std::make_pair("a",1 ));
       m.insert(std::make_pair("b",8 ));
       m.insert(std::make_pair("v",5 ));
    
       for(std::map<std::string, int>::iterator i = m.begin(); i != m.end(); ++i ) {
         v.push_back(*i);
       }
    
       std::cout << "unsorted\n";
       for(std::vector<string_int_pair>::iterator i = v.begin(); i != v.end(); ++i ) {
          std::cout << (*i).first << " " << (*i).second << std::endl;
       }
    
       std::sort(v.begin(), v.end(), Sorter()); 
    
       std::cout << "sorted\n";
       for(std::vector<string_int_pair>::iterator i = v.begin(); i != v.end(); ++i ) {
          std::cout << (*i).first << " " << (*i).second << std::endl;
       }
    }
    

    output

    unsorted
    a 1
    b 8
    v 5
    sorted
    a 1
    v 5
    b 8
    

    Kurt



  • @niemand

    Also so geht es auch nicht. Ich muss nämlich auch die Anzahl der Eigenschaften hin und wieder erhöhen. Deswegen hatte ich am Anfang map<string,int>, weil ich dann einfach map["Eigenschaft"] += 1 machen konnte. Wie das bei dir funktionieren soll ist mir nicht ganz klar. Irgendwie müsste der Vektor dann ja auch aktualisert werden.



  • Das ist klar. Du musst den vektor jedesmal neu erzeugen und sortieren wenn du die map nach value sortiert ausgeben möchtest. Eine bessere lösung fällt mir nicht ein.
    Kurt



  • @ZuK

    Sieht so aus als wenn es funktioniert. Ich werde es morgen mal in mein Programm einbauen und gucken wie es läuft, denke aber dass es jetzt stimmt. Ich melde mich dann nochmal.

    Auf jeden Fall schonmal danke für das Interesse bzw. die zahlreichen Antworten 🙂



  • ZuK schrieb:

    Das ist klar. Du musst den vektor jedesmal neu erzeugen und sortieren wenn du die map nach value sortiert ausgeben möchtest. Eine bessere lösung fällt mir nicht ein.
    Kurt

    Das ist schon OK so denke ich, weil die Map erst erzeugt wird und anschließend ausgegeben wird.



  • So, es funktioniert. Also vielen Dank nochmal 🙂


Anmelden zum Antworten