std::map insert



  • Hallo,

    ich kopiere Elemente in eine std::map via Insert().
    Der neue Eintrag in der Map wird jedoch Alphabetisch sortiert.
    Wie kann ich das verhindern ? Es soll at end angehangen werden.

    Beispiel:

    std::map<std::string, std::string> params;
    
    params.insert(std::map<std::string, std::string>::value_type("Baum","grün"));
    params.insert(std::map<std::string, std::string>::value_type("Auto","rot"));
    

    Ergebnis: //alphabetisch sortiert
    (0) Auto rot
    (1) Baum grün

    Erwünscht: //unsortiert wie eingegeben
    (0) Baum grün
    (1) Auto rot

    Ausgelesen wird das so:

    for (std::map<std::string, std::string>::const_iterator i = r->m_params.begin(); i != r->m_params.end(); i++)
    {
      CString &param(i->first.c_str() + CString("=") + i->second.c_str());
    }
    

    Mir ist klar das der erste Eintrag von zwei als index gild , aber
    die Speicherfolge kann doch gleich der eingabe folge sein.

    Danke für Hinweise
    Karsten



  • Wenn du das unbedingt brauchst, nimm einen std::vector<std::pair<std::string, std::string>>.



  • Hallo,
    ich kann leider keinen Vector verwenden da andere diese map
    weiter verarbeiten.

    Muss ich also eine zweite Liste zur indizierung parallel verwenden,
    das ist sehr unschön. ich kann dem feld auch keinen dritten Eintrag zuweisen.



  • Wieso brauchst du denn eine Ordnung?
    Und was heißt "a andere diese map weiter verarbeiten."?
    Wieso gehen denn dann zwei Listen*?

    *Ich hoffe du meinst jetzt nicht std::list. std::list ist für 90+% der Anwendungsfälle ungeeignet...



  • Es ist ein Webserver, der umfangreich
    mit diesem Array arbeitet. Ich kann nicht die ganze verarbeitung
    verändern, am Ende brauche ich eine historisch indizierte Liste,
    bekomme aber eine alphabetisch sortierte, der Voreintrag bestimmt
    später die Sortiergruppe der Einträge. Die "anderen" sind andere
    Programmteile.



  • Und wieso geht dann der std::vector nicht?



  • weil er nicht zwei teile nebeneinander ablegt:

    i->first.c_str()

    i->second.c_str()

    Ich muss mich den anderen Aufgaben unterordnen , diese verwenden nun mal
    map, da kann man nicht einfach alle konzepte verwerfen, ich denke
    eher es gäbe eine Option um das Alphabetische sortieren im Vorfeld
    zu unterdrücken und gut ist.

    Wenn dem nicht so ist, muss ich eine indizierliste parallel erzeugen
    was man nicht möchte.



  • struct Comp
    {
      bool operator()(const std::string& lhs, const std::string& rhs) const
      {
        // implement your comparison logic here
      }
    };
    

    Instances of this class is callable (hence "functor") with two string parameters, and should return true or false based in a strict weak ordering logic.

    Then instantiate the map using the functor type:

    std::map<string, list<pair<string, int>>, Comp> List;
    

    Now the map will use your comparison logic internally to define the ordering of its elements.

    Fummelig, ein Sortflag wäre ja nicht schlecht gewesen....



  • std::map erfordert eine konsistente Sortierung. Wenn du nach Zeit sortieren willst, musst du ein entsprechendes Attribut als Key einfügen. std::string -Keys in einer Map chronologisch zu ordnen ist nicht möglich.

    Aber wie gesagt, std::map ist der falsche Container. Wer sowas vorschreibt, hat keine Ahnung, oder du hast ein paar Details in der Aufgabenstellung vergessen. Wieso genau musst du std::map verwenden?

    P.S. Nächstes Mal kannst du gleich sagen, wenn du noch auf StackOverflow nachfragst.



  • Ich habe nicht gefragt, sondern die Suche intensiviert.
    Und ich verstehe die Unterschiede, es ging um die
    Option der chronologischen beeinflußung im Vorfeld.
    ich bau das nun um, nach std::vector

    Danke für deine Hilfe.

    Gruß K.



  • Es ist schon irgendwie möglich mit std::map , z.B. indem man einen Index mitführt wie in der StackOverflow-Antwort.

    Aber es ist wahnsinnig ineffizient und umständlich, wenn es nur darum geht, die Einfügereihenfolge beizubehalten. Du verlierst all die Vorteile von std::vector (schnelle Speicherbeschaffung, keine Speicherfragmentierung und dadurch weniger Cache-Misses, wenig Speicherverbrauch, Random Access). Einen produktiven Einsatz würde ich also nicht empfehlen, zumal du noch immer keine eigentlichen Gründe dafür genannt hast.

    Wenn du unbedingt bei der Index-Lösung bleiben willst:

    map<string, list<pair<string, int>>>
    

    wie auf StackOverflow vorgeschlagen ist merkwürdig, warum den Index im Value und nicht Key speichern? Key ist ja das, wonach sortiert wird. Und warum kommt überhaupt der Vorschlag, den Index in den String einzubauen? Mehr Sinn würde also

    map<pair<size_t, string>, string>
    

    machen. Wenn der Index als erstes Element im std::pair gespeichert wird, wird automatisch danach sortiert wird und du musst gar keinen Funktor schreiben. Wenn du Mehrfacheinträge brauchst, nimm std::multimap . Zudem braucht std::list sehr gute Argumente um eingesetzt zu werden. Für Indizes solltest du für Indizes std::size_t und nicht int nehmen.

    Edit: Ah, hab vorher was überlesen. Wenn das so umständlich sein muss, vergiss den letzten Absatz.

    Dass du zusätzlich auf StackOverflow nachfragst ist kein Problem, aber es wäre nett das zu erwähnen 😉



  • Möglicherweise ist boost::bimap eine Option?


Log in to reply