in veschachtelter map nach paar suchen: map<pair<long, long>, double> matrix
-
hallo,
ich habe mir folgende map angelegt:
map<pair<long, long>, double> matrix;wobei die beiden long-werte jeweils koordinaten abbilden und der double-wert eben der wert zu den bestimmten koordinaten ist.
jetzt habe ich hunderte von einträgen in meiner map und möchte schauen, ob eine bestimmtes koordinatepaar in meiner map existiert.ich dachte da an
map<pair<long, long>, double>::iterator it matrix.find(x, y); if(it != matrix.end()) { // .. }der input bei find() geht leider nicht, ich weiß aber auch nicht wie ich sonst nach dem koordinatenpaar suchen sollte.
ein
pair<long, long> a = pair<long, long>(2, 3);und dann nach a suchen geht auch nicht.
hat jemand eine andere idee?
dankeschön
-
Hallo,
map<pair<long, long>, double>::iterator it = matrix.find(pair<long, long>(x, y));oder
map<pair<long, long>, double>::iterator it = matrix.find(make_pair(x, y));
-
Du mußt einen eigenen Datentypen definieren, und für diesen den Kleiner-Operator "operator<" definieren.
Ungefähr soclass Koordinate { public: Koordinate (long x, long y) : x_(x), y_(y) {} long x_, y_; } bool operator< (Koordinate const& lhs, Koordinate const& rhs); // Operator aus der Klasse gezogen std::map<Koordinate, double> matrix;Ergänzung: Oder Du übergibst einen Functor
class ComparePair { public: bool operator() (std::pair<long, long> lhs, std::pair<long, long> const& rhs); }; map<pair<long, long>, double, ComparePair> matrix;
-
Vergleichsoperatoren sollten global sein. Desweiteren hat pair schon einen operator<
-
Ups, das habe ich gerade übersehen. Vermutlich ist es trotzdem gut einen eigenen Vergleichsoperator zu definieren.
-
das sieht gut aus, manchmal ist man viel näher dran als man glaubt. der braunsteinsche weg ist jetzt bei mir im einsatz, besten dank! ich glaube für meine anforderung sollte diese lösung dann auch ausreichen, dennoch vielen dank für deine mühe, ~john..
auf wiederlesen
-
~john schrieb:
Ups, das habe ich gerade übersehen. Vermutlich ist es trotzdem gut einen eigenen Vergleichsoperator zu definieren.
Wenn dir das Verhalten des eingebauten Operators nicht gefällt kannst du das ja machen. Trotzdem ist es hier nicht nötig dafü eine separate struct zu bauen (obwohl auch kein Problem). Es würde hier reichen einen operator< für pair<long,long> zu erzeugen.
-
einandermappe schrieb:
ein
pair<long, long> a = pair<long, long>(2, 3);und dann nach a suchen geht auch nicht.
Kürzer:
pair<long, long> a(2, 3);
-
Braunstein schrieb:
Es würde hier reichen einen operator< für pair<long,long> zu erzeugen.
Das wiederum halte ich für keinen guten Gedanken, da man damit das Verhalten des Standard Operators überdeckt. Und wer weiß, ob man pair<long,long> nicht noch an anderer Stelle benötigt. (Überhaupt halte ich es für sinnvoller Koordinaten in einer eigenen Klasse zu verwalten.)
Edit
Überflüssiges gelöscht.
-
Man muß diesen Operator ja nicht global definieren. Desweiteren überdeckst du hier keinen Operator sondern machst eine Spezialisierung für <long,long>.
Inwiefern unterscheidet sich deine Variante von meiner Zweiten (oder meinst du die verwendung des CopyCtor).
[edit]
@phalanx-fanboy
Das ist natürlich kürzer zu schreiben. Der Compiler macht natürlich aus beiden Varianten den gleichen Code.
[edit]
-
Braunstein schrieb:
Man muß diesen Operator ja nicht global definieren. Desweiteren überdeckst du hier keinen Operator sondern machst eine Spezialisierung für <long,long>.
Hm, gefällt mir persönlich nicht so sehr.
Inwiefern unterscheidet ...
Irgend wie bin ich beim Lesen der Beiträge in diesem Thread nicht wirklich aufmerksam. Also, nichts für ungut
-
Braunstein schrieb:
Vergleichsoperatoren sollten global sein. Desweiteren hat pair schon einen operator<
Dafür gibt es keinen guten Grund. Normalerweise sollten Operatoren wie andere freie Funktionen sich im assozierten Namensraum der Klasse befinden, zu der sie gehören. Für std::pair wäre das der Namensraum std - und wie richtig erwähnt wurde, existiert dort ein operator< für pair.
In diesem speziellen Falle kann man auf biegen und brechen einen globalen operator< für pair<long,long> definieren, der kein Template ist (in einem anderen Namensraum würde er nicht gefunden werden, denn das Prädikat, dass benutzt wird ist std::less - dieses durchsucht folglich nur den Namensraum ::std, den globalen Namensraum und die assozierten Namensräume der Parameter, die aber hier (mit std::pair<long,long>) mit ::std zusammenfallen). Das ist aber - wie ich schon in einem anderen Thread meinte - zu brutal. Die Regel, dass überladene Operatoren immer ein UDT als Parameter benötigen, findet ihren Grund darin, dass der bereits vorgegeben Teil der Sprache nicht verändert werden kann: Die Semantik von x<y für zwei ints x,y ist vorgegeben und kann nicht verändert werden. Diese Argumentation kann genauso gut auf die Datentypen der Standardbibliothek angewendet werden - allerdings ist die Sprache selbst nicht in der Lage, einen derartigen Schutz zu bieten, mithin sind solche Scheußlichkeiten möglich; trotzdem sollten sie so gut wie immer tabu sein.
-
... das sieht doch nach dünnbesetzten matrizen aus.
ich hab das so implementiert:
std::vector<std::map<int, float> > matrix;... und denke das suchoperationen darauf schneller ausgeführt werden.