Frage zur Verbesserung der Performance von bestimmtem Algorithmus
-
1. Deine Schleife funktioniert nicht richtig. Das
eofbitFlag wird erst gesetzt, wenn über das Ende hinaus gelesen wurde. Du wirst dadurch einen Eintrag zu viel lesen, bzw. wahrscheinlich einfach doppelt eintragen. Frag nach dem Einlesen ab, ob das Einlesen korrekt verlaufen ist, bzw. ob der Stream noch gültig ist. Nutze dazu den Rückgabewert vonoperator >>aus
2. Ich würde alle Einträg einfach einlesen. Danach mitstd::sortSoriteren und am Ende mitstd::uniquedoppelte Einträge rauslöschen.Grüssli
-
Ok, Dravere's Problemlösung ist gut, allerdings in meinem Fall nicht anwendbar. Dazu muss ich etwas ausholen:
Die Klasse hat neben id weitere Eigenschaften. Unter andem eine... nenn wir sie version. Wenn ein eingelesenes Objekt eine id besitzt, die es schon im Vector gibt, dann wird die version der schon vorhandenen id hinzugefügt:class Klasse { std::string id; std::vector<int> version; //... }; std::vector<Klasse> vec; int main() { vec.reserve(20000); std::ifstream lesen("Database"); bool gefunden = false; while(!lesen.eof()) { Klasse objekt; lesen>>objekt; for(size_t a(0), b(vec.size()); a!=b; ++a) { if(objekt.id == vec[a].id) { vec[a].version.push_back(objekt.version[0]); gefunden=true; break; } } if(gefunden) { gefunden=false; continue; } vec.push_back(objekt); } }
-
Muss die Klasse so sein wie sie ist mit dem Version-vector? Was du da fabrizierst ist nämlich reichlich umständlich und sieht ein wenig nach suboptimalem Design aus. Was genau ist denn die Aufgabenstellung/was genau willst du erreichen?
-
Abgesehen von dem was pumuckl gesagt hat, könntest du deinen eigenen
uniqueAlgorithmus einbauen. Es gibt sogar bereits andere Algorithmen, welche dir dabei behilflich sein könnten. Zum Beispiel:
http://www.cplusplus.com/reference/algorithm/adjacent_find/So kompliziert ist der Algorithmus ja wirklich nicht.
Grüssli
-
[Edit] Was übersehen...
Genauso wie es Draveres Vorschlag tut. Lies alle Werte ein, sortier und füll dann erst den Versionsvektor auf mit den doppelten Elementen, die folgen. Zum Schluss die doppelten Objekte entfernen.
-
Die idee mit adjacent_find und dann die doppelten Elemente über unique löschen find ich gut! Werd die gleich mal implementieren!
-
adjacent_find hat sich als nicht so gut herausgestellt, da von einer id durchaus mehr als 2 vorkommen können. Ich habe jetzt versucht das selbst zu implementieren. Allerdings habe ich am ende statt ca. 15000 Objekten nur ca. 5000 im vector. Sieht jemand den Denkfehler?
class Klasse { std::string id; std::vectir<int> version; //... } inline bool sort_all ( const Klasse& a, const Klasse& b){ return (a.id < b.id); } inline bool operator==(const Klasse& a, const Klasse& b){ return (a.id == b.id); } std::vector<Klasse> vec; int main() { vec.reserve(20000); while(!lesen.eof()) { Klasse objekt; // lesen>>objekt; // alle einlesen vec.push_back(objekt); // } lesen.close() std::vector<Klasse>::iterator it=vec.begin(), end=vec.end(), at, unique_it; sort(it, et, sort_all); //vec sortieren at = it; ++it; while(at != end) { if(*it == *at) { (*it).version.push_back( (*at).version[0] ); ++at; continue; } it = at; ++at; } unique_it = unique(vec.begin(), end); vec.resize(end-unique_it); }
-
*edit: ++it in Zeile 29 sollte ++at heißen
-
Was hast du denn gegen adjacent_find()=
typedef vector<Klasse>::iterator Iter; Iter pos1 = vec.begin(); Iter pos2; while((pos1 = adjacent_find(pos1, vec.end())) != vec.end()) { pos2 = pos1 + 1; while(*pos2 == *pos1) { pos1->version.push_back(pos2->version[0]); ++pos2; if(pos2 == vec.end()) return; // aus beiden Schleifen raus } pos1 = pos2 + 1; }Wie immer ungetestet.
[Edit] OK, hier kann man sich adjacent_find() wirklich sparen

-
Offensichtlich hast du meinen "falschen" Code 1:1 mit adjacent_find umgesetzt
Mit deinem und meinem Ansatz bekomme ich genau 5697 Elemente in den vector, obwohl am ende ca. 15000 drin sein sollten 
-
Michael E.'s code funktioniert wunderbar. Hatte mich mit unique() vertan. Jetzt geht das einlesen in unter einer sekunde. Danke!