Inhalt zweier Container auf Doubletten untersuchen und fehlende auflisten.
-
servus,
ich habe zwei container vom typ map<string, string>.
Ich interessiere mich nur für den Key, also den ersten String. Inhalt des zweiten ist egal.Die beiden maps enthalten "fast" das gleiche, also einige Keys sind sowohl in der einen wie auch in der anderen map drin.
Was ich gerne hätte ist eine Iteration über beide Maps, die mir folgende Ausagbe gibt:
Foo ist nur links. Bar ist in beiden. Baz ist nur rechts. Blub ist in beiden. Blah ist in beiden. Heuwägelchen ist nur links. usw...Das ist mein Ansatz:
typedef std::map<std::string, std::string> smap; int main() { smap oldmap, newmap; put_stuff_in_maps(); smap::const_iterator ni = newmap.begin(); smap::const_iterator ne = newmap.end(); smap::const_iterator oi = oldmap.begin(); smap::const_iterator oe = oldmap.end(); for (;;) { while (ni != ne && ni->first < oi->first) { std::cerr << ni->first << " only in new data." << std::endl; ++ni; } while ((ni!=ne && oi!=oe) && oi->first == ni->first) { std::cout << ni->first << " both in old and new data." << std::endl; ++ni; ++oi; } if (ni == ne) break; while (oi != oe && oi->first < ni->first) { std::cerr << oi->first << " only in old data." << std::endl; ++oi; } if (oi == oe) break; } return EXIT_SUCCESS; }Funktioniert auch schon beinahe. Mein Problem ist, ich krieg die Abbruchbedingungen nie so hin dass er sowohl beide maps bis zum Ende abarbeitet als auch nicht in eine Endlosschleife hängen bleibt als auch nicht zwischendurch beim stringcompare segfaulted, weil ein iterator schon auf end() steht.
Die obere variante segfaultet zwar nicht und bleibt auch nicht in einer endlos-loop hängen, aber ich hab das Gefühl, sie bricht manchmal zu früh ab.
Wer findet den Fehler?
-
Schaue dir mal std::mismatch an.
Du musst ledliglich einen Prädikat übergeben, was aus == != macht.
-
ich suche den Fehler nicht. Aber alles wird viel einfacher, wenn du pro for-loop iteration jeden iterator maximal einmal incrementierst, abbrichst wenn einer der iteratoren am Ende ist und zum schluss noch die elemente der anderen map ausgibst
und ich hoffe, in deinem code sind die Namen ursprünglich hübscher.
while(ni != ne && oi != oe){ if(ni->first < oi->first){ std::cerr << ni->first << " only in new data." << std::endl; ++ni; } else if(oi->first < ni->first){ std::cerr << oi->first << " only in old data." << std::endl; ++oi; } else{ std::cout << ni->first << " both in old and new data." << std::endl; ++ni; ++oi; } } for(;ni != ne;++ni){ std::cerr << ni->first << " only in new data." << std::endl; } while(oi != oe){ std::cerr << oi->first << " only in old data." << std::endl; ++oi; }
-
otze schrieb:
for(;ni != ne;++ni){ std::cerr << ni->first << " only in new data." << std::endl; } while(oi != oe){ std::cerr << oi->first << " only in old data." << std::endl; ++oi; }Gespaltene Persönlichkeit?
-
hustbaer schrieb:
otze schrieb:
for(;ni != ne;++ni){ std::cerr << ni->first << " only in new data." << std::endl; } while(oi != oe){ std::cerr << oi->first << " only in old data." << std::endl; ++oi; }Gespaltene Persönlichkeit?

Und wieso eigentlichstd::cerr?
-
hustbaer schrieb:
Gespaltene Persönlichkeit?
Nein, müde + copy& paste.
-
@otze funktioniert einwandfrei, danke.
Std::cerr kam von mir, ich wollte die, die nicht doubletten sind, in der Konsole in rot haben.
-
BTW: Ich finde die Lösung grundsätzlich gut (übersichtlich, verständlich), nur die letzten beiden Schleifen finde ich unnötig:
while (ni != ne || oi != oe) { if (oi == oe || ni->first < oi->first) { std::cerr << ni->first << " only in new data." << std::endl; ++ni; } else if (ni == ne || oi->first < ni->first) { std::cerr << oi->first << " only in old data." << std::endl; ++oi; } else { std::cout << ni->first << " both in old and new data." << std::endl; ++ni; ++oi; } }DRY und so