ids einer map schnell ändern
-
volkard schrieb:
Einen Wrapper um die map machen, der beim Durchschleifen den Offset addiert bzw. subtrahiert.
vll. gibts da was wie std::offset(int) ?!
-
asdsad schrieb:
volkard schrieb:
Einen Wrapper um die map machen, der beim Durchschleifen den Offset addiert bzw. subtrahiert.
vll. gibts da was wie std::offset(int) ?!
Nein was gemeint ist, ist folgendes:
class MyMap { private: std::map<int, Foo> map; int offset; public: void setOffset(int offset) { this->offset = offset; } Foo& operator[](int id) { return map[id+offset]; } };bzw. statt offset kann ja auch eine Funktion verwendet werden die die ID korrekt transformiert.
Sowas ist deutlich effizienter als die map jedesmal neu aufzubauen mit anderen keys.
-
Shade Of Mine schrieb:
asdsad schrieb:
volkard schrieb:
Einen Wrapper um die map machen, der beim Durchschleifen den Offset addiert bzw. subtrahiert.
vll. gibts da was wie std::offset(int) ?!
Nein was gemeint ist, ist folgendes:
class MyMap { private: std::map<int, Foo> map; int offset; public: void setOffset(int offset) { this->offset = offset; } Foo& operator[](int id) { return map[id+offset]; } };bzw. statt offset kann ja auch eine Funktion verwendet werden die die ID korrekt transformiert.
Sowas ist deutlich effizienter als die map jedesmal neu aufzubauen mit anderen keys.
Kann leider an der schnittstelle nichts ändern, sie verlangt eine map... ich überlege einen cast operator für die o.g. MyMap zu schreiben aber das wäre dann etwas dirty..
-
asdsad schrieb:
vll. gibts da was wie std::offset(int) ?!
http://www.cplusplus.com/reference/clibrary/cstddef/offsetof/
Aber das ist nur eine Namensähnlichkeit und hier nicht zielführend.
-
asdsad schrieb:
Kann leider an der schnittstelle nichts ändern, sie verlangt eine map... ich überlege einen cast operator für die o.g. MyMap zu schreiben aber das wäre dann etwas dirty..
dh du kannst auch nicht die Klasse ändern die als Key verwendet wird? Sonst könnte man dort nämlich am operator< ansetzen.
Dann fällt mir aber nichts mehr ein und man muss echt dumm kopieren.
Was kannst du denn ändern? Vielleicht fällt uns so eine Lösung ein...
-
asdsad schrieb:
Kann leider an der schnittstelle nichts ändern, sie verlangt eine map... ich überlege einen cast operator für die o.g. MyMap zu schreiben aber das wäre dann etwas dirty..
Verlangt sie auch eine map<int> oder darfs eine map<offsettable_int<&global_offset>> sein?
-
Das Problem ist, dass du die Keys einer Map nicht ändern darfst, selbst wenn die Sortierung anschliessend erhalten bleibt. Wenn du also nach wie vor eine
std::map<int, X>benötigst, gibt es keinen anderen standardkonformen Weg, als eine neue Map mit verschobenen Indizes zu erstellen.
-
Danke schonmal an alle Antwortenden
Shade Of Mine schrieb:
asdsad schrieb:
Kann leider an der schnittstelle nichts ändern, sie verlangt eine map... ich überlege einen cast operator für die o.g. MyMap zu schreiben aber das wäre dann etwas dirty..
dh du kannst auch nicht die Klasse ändern die als Key verwendet wird? Sonst könnte man dort nämlich am operator< ansetzen.
Dann fällt mir aber nichts mehr ein und man muss echt dumm kopieren.
Was kannst du denn ändern? Vielleicht fällt uns so eine Lösung ein...Leider nicht... es wird eine std::map<int,Target> erzwungen die beginnend von 1 gefüllt wird während eine andere Klasse die ich ebenfalls nicht ändern kann für bestimmte Aufgaben ids beginnend ab 10000 benötigt weil sie die Zuordnung anhand von eben diesen Offsets vornimmt. Ich dachte da gäbe es etwas konventionelles einzeiliges...
-
Es gibt schon Möglichkeiten, aber das Verhalten ist laut C++-Standard undefiniert, weil Keys in einer Map nicht geändert werden dürfen.
std::map<int, X> m; std::for_each(m.begin(), m.end(), [] (std::pair<const int, X>& p) { const_cast<int&>(p.first) += 1000; } );
-
Angst hab, weil früher oder später irgendwann jemand die Iteratoren so bastelt, daß sie von der Ordnung abhängen, fürchte ich.
Aber bei for_each(m.regin(), m.rend() hätte ich keine Angst mehr.
-
Nexus schrieb:
Es gibt schon Möglichkeiten, aber das Verhalten ist laut C++-Standard undefiniert, weil Keys in einer Map nicht geändert werden dürfen.
std::map<int, X> m; std::for_each(m.begin(), m.end(), [] (std::pair<const int, X>& p) { const_cast<int&>(p.first) += 1000; } );Die Reihenfolge ändert sich ja (in diesem Fall) nicht. Aber danke für den Tipp..
-
asdsad schrieb:
Die Reihenfolge ändert sich ja (in diesem Fall) nicht.
Trotzdem ist es undefiniertes Verhalten. Eine Map-Implementierung darf davon ausgehen, dass die Keys sich nie ändern, und darauf basierend z.B. irgendwelche Optimierungen anstellen. Wenn du als Benutzer diese Garantie brichst (mit
const_castals Brecheisen), musst du auch Manns genug sein, die Konsequenzen zu tragen.Von daher: Kopier die Map lieber.
-
Nexus schrieb:
Von daher: Kopier die Map lieber.
Ich glaube da bleibt nichts anderes übrigt.
Danke an alle nochmal.
-
Ist der entsprechende Abschnitt in deinem Code wirklich derart performancekritisch?
Falls du die Geschwindigkeit nicht unbedingt brauchst, würde ich nicht lange überlegen, um zwischen einer standardkonformen und einer schnellen Lösung zu entscheiden.
-
Nexus schrieb:
Ist der entsprechende Abschnitt in deinem Code wirklich derart performancekritisch?
Falls es "nur effizient" sein soll, würde ich nicht lange überlegen, um zwischen einer standardkonformen und einer schnellen Lösung zu entscheiden.
Ich bin eigentlich mit dem Gedanken hierher gekommen dass es dafür einen "simplen" standardkonformen Einzeiler gäbe den ich noch nicht kannte. Zumindest kam es mir wie eine alltägliche Aufgabe vor. Es ist weder kritisch noch notwendig.
-
Reicht ein Zweizeiler?

std::map<int, Target> shiftedIndex; std::transform(original.begin(), original.end(), std::inserter(shiftedIindex, shiftedIndex.end()), [](std::pair<int, Target> const& vt) { return std::make_pair(vt.first+10000, vt.second); });siehe http://ideone.com/jaCyg#
mal im Ernst: Ob man jetzt einen "Einzeiler" hat oder ob das durch eine selbstgeschrieben Funktion mit 3-4 Zeilen erledigt werden kann ist am Ende doch auch herzlich egal, oder?
-
pumuckl schrieb:
Reicht ein Zweizeiler?

std::map<int, Target> shiftedIndex; std::transform(original.begin(), original.end(), std::inserter(shiftedIindex, shiftedIndex.end()), [](std::pair<int, Target> const& vt) { return std::make_pair(vt.first+10000, vt.second); });siehe http://ideone.com/jaCyg#
mal im Ernst: Ob man jetzt einen "Einzeiler" hat oder ob das durch eine selbstgeschrieben Funktion mit 3-4 Zeilen erledigt werden kann ist am Ende doch auch herzlich egal, oder?
Wenn man ein guter Programmierer ist schon. Ich habe allerdings wenig Zeit und bin immer froh wenn so etwas schon in der stl abgeckt ist weil ich es selber wohl nicht besser hinkriege.
Danke für deinen Tipp. Sieht auch sehr interessant aus.