Frage zu Vector mit Iterator
-
Hallo Leute,
habe da mal wieder ne Frage.
Habe ein Programm geschrieben, was mir Daten aus einer Datenbank liest und in einen Vector mit einen Struc schreibt. Dabei suche ich im Vector immer auf vorhandensein eines Wertes.
Das ganze läuft recht gur und schnell. Aber bei größeren Datenmengen wird es immer langsamer. Jetzt habe ich von Iterator gelesen, kann aber damit noch nichts anfangen, vor allem nicht welchen Iterator man wie und wann benützen kann.
Kann mir vielleicht jemand erklären wie das mit den Iteratoren funktioniert oder eine Beschreibung dafür hat ?? Wenn es geht in Deutsch ??
Hier ein code mit der Durchsuchung des Vectors nach meiner art:
struct struStatistik_Benutzer { int iID; int iID_Statistik_Gruppen; std::string strProfil_ID; std::string strBenutzer; std::string strMaschine; }; void CStatistikSucheDialog::StatistikBenutzerEingabe(std::string u_strBenutzername, std::string u_strMaschinenname, std::string u_strProfilID, int u_iIDStatistikGruppen) { struStatistik_Benutzer m_struStatistikBenutzer; BOOL STATUS = FALSE; for(unsigned i = 0; i < m_vStatistik_Benutzer.size(); i++) { if(u_strBenutzername == m_vStatistik_Benutzer[i].strBenutzer && u_strMaschinenname == m_vStatistik_Benutzer[i].strMaschine && u_iIDStatistikGruppen == m_vStatistik_Benutzer[i].iID_Statistik_Gruppen && m_vStatistik_Benutzer[i].strProfil_ID == u_strProfilID) { STATUS = TRUE; i = m_vStatistik_Benutzer.size(); } else { STATUS = FALSE; } } if(STATUS == FALSE) { m_struStatistikBenutzer.iID =m_vStatistik_Benutzer.size() + 1; m_struStatistikBenutzer.iID_Statistik_Gruppen = u_iIDStatistikGruppen; m_struStatistikBenutzer.strProfil_ID = u_strProfilID; m_struStatistikBenutzer.strBenutzer = u_strBenutzername; m_struStatistikBenutzer.strMaschine = u_strMaschinenname; m_vStatistik_Benutzer.push_back(m_struStatistikBenutzer); } }
Gruß
andy_mann
-
Erstmal: Diene Benennung ist sehr komisch: Warum struStatistik_Benutzer...? Wofür steht stru? Warum wird Status komplett groß geschrieben? Warum hast du ein eigenes BOOL? Welche vorteile bietet es gegenüber dem normalen bool?
Warum testest du beim Vergleich nicht erst die Dinge, die schnell vergleichbar sind (also die int-sachen)? Kennst du das Short-Cirquit-Verhalten nicht? Dadurch könntest du vielleicht was geschwindigkeit rausholen.
Zu den iteratoren:
Wenn du einen vector hast:std::vector<Benutzer_Statistik> meinVector;
Dann kannst du so passende Iteratoren anlegen:
std::vector<Benutzer_Statistik>::iterator einIterator;
Iteratoren verweisen immer auf eine stelle in deinem Vektor. Du kannst mit ihnen quasi genau so arbeiten, wie mit Zeigern. Du kannst also den Wert, auf den sie verweisen mit * abfragen, sie auf den nächsten wert verweisen lassen, indem du ++ anwendest, ...
vector bietet eine Methode begin, um einen Iterator auf das erste Element zu erzeugen und end um einen Iterator zu erzeugen, der hinter das letzte Element verweist. So kannst du sehr bequem schleifen aufbauen:
for(vector<Statistic_Benutzer>::iterator it=m_vStatistik_Benutzer.begin(); it!=m_vStatistik_Benutzer.end(); ++it) { if(u_iIDStatistikGruppen == it->iID_Statistik_Gruppen && it->strProfil_ID == u_strProfilID && u_strBenutzername == it->strBenutzer && u_strMaschinenname == it->strMaschine) { STATUS = TRUE; i = m_vStatistik_Benutzer.size(); } else { STATUS = FALSE; } }
Und las den scheiß von wegen str..., u_str... etc.
-
Vielen Dank,
funktioniert auch, geschwindichkeits verbesserung konnte ich jetzt aber noch nicht fest stellen.
Zu meiner Namensgebzng, ja ich weiss, könnte vielleicht mit besseren Namensfindung verbessert werden, ich komme aber damit zurecht.
Das große BOOL kommt von der MFC, dort wird es so gemacht.Mein tool wird in der MFC geschrieben, benutzen tue ich aber die STL klassen.
Gruß
andy_mann
-
Man könnte das ganze sicherlich auch übersichtlicher gestalten:
statt
if(u_iIDStatistikGruppen == it->iID_Statistik_Gruppen && it->strProfil_ID == u_strProfilID && u_strBenutzername == it->strBenutzer && u_strMaschinenname == it->strMaschine) { STATUS = TRUE; i = m_vStatistik_Benutzer.size(); } else { STATUS = FALSE; }
STATUS = u_iIDStatistikGruppen == it->iID_Statistik_Gruppen && it->strProfil_ID == u_strProfilID && u_strBenutzername == it->strBenutzer && u_strMaschinenname == it->strMaschine); if (STATUS) break;
-
Ich hatte nämlcih beim ersten mal dein i= ... in der schleife nicht verstanden. Wen du solche bekloppten Tricks machst solltest du das kommentieren, oder noch besser einfach auf break zurückgreifen.
-
ääähhhh...
ich weiss nicht genau auf was du hinaus willst.
mit der Namensgebung und der Schreibweise, kann man drüber streiten.
Ich kann es halt so besser lesen.Was dieses Funktion machen soll ist, den Vector durchlaufen, nach Kriterien suchen, falls vorhanden die Stelle (ID) zurück geben, falls nicht neuen Eintrag hinzu.
Gruß
andy_mann
-
Dein
i = m_vStatistik_Benutzer.size();
funktioniert in der iteratorvariante doch gar nicht mehr. Du müsstest es ändern. ein einfaches break ist da doch viel schöner.
Was dieses Funktion machen soll ist, den Vector durchlaufen, nach Kriterien suchen, falls vorhanden die Stelle (ID) zurück geben, falls nicht neuen Eintrag hinzu.
Macht sie aber nicht. Ihr rückgabetyp ist void somit gibt sie schonmal garnichts zurück.
Warum meine version schöner ist?
Du machst folgendes: Teste, ob die Bedinung true ist. wenn sie das ist setze auch status auf true. Wenn die bedinugn allerdings nicht true ist (also wenn sie false ist), dann setze auch den Status auf false. Ich sage einfach der Status ist der Wert der Bedinung.
-
Bleibt natürlich noch die Frage, warum deine Struktur keinen Konstruktor hat. Und dann auch gleich noch ein Vergleichsoperator:
struct struStatistik_Benutzer { int iID; int iID_Statistik_Gruppen; std::string strProfil_ID; std::string strBenutzer; std::string strMaschine; struStatistik_Benutzer (int id, int statistikGruppenID, std::string const & profilID, std::string const & benutzer, std::string const & maschine) : iID(id) , iID_Statistik_Gruppen(statistikGruppenID) , strProfil(profilID) , strBenutzer(benutzer) , strMaschine(maschine) {} }; bool operator == (struStatistik_Benutzer const & lhs, struStatistik_Benutzer const & rhs) { return lhs.iID_Statistik_Gruppen == rhs.iID_Statistik_Gruppen && lhs.strProfil == rhs.strProfil && lhs.strBenutzer == rhs.strBenutzer && lhs.strMaschine == rhs.strMaschine; }
Dann könnte man deinen ganzen Mist doch gleich viel einfacher schreiben.
void CStatistikSucheDialog::StatistikBenutzerEingabe(std::string u_strBenutzername, std::string u_strMaschinenname, std::string u_strProfilID, int u_iIDStatistikGruppen) { struStatistik_Benutzer m_struStatistikBenutzer(m_vStatistik_Benutzer.size() + 1, u_iIDStatistikGruppen, u_strProfilID, u_strBenutzername, u_strMaschinenname); BOOL STATUS = std::find(m_vStatistik_Benutzer.begin(), m_vStatistik_Benutzer.end(), m_struStatistikBenutzer) != m_vStatistik_Benutzer.end(); if(STATUS == FALSE) { m_vStatistik_Benutzer.push_back(m_struStatistikBenutzer); } }
oder in kurz:
void CStatistikSucheDialog::StatistikBenutzerEingabe(std::string u_strBenutzername, std::string u_strMaschinenname, std::string u_strProfilID, int u_iIDStatistikGruppen) { struStatistik_Benutzer m_struStatistikBenutzer(m_vStatistik_Benutzer.size() + 1, u_iIDStatistikGruppen, u_strProfilID, u_strBenutzername, u_strMaschinenname); if(std::find(m_vStatistik_Benutzer.begin(), m_vStatistik_Benutzer.end(), m_struStatistikBenutzer) == m_vStatistik_Benutzer.end();) { m_vStatistik_Benutzer.push_back(m_struStatistikBenutzer); } }
-
Dann musst du die String-Argumente nurnoch als konstante Referenz übergeben und schon ist das ganze ordentlich schnell.
-
Ohhhh, vielen Dank,
dass sieht natürlich Profesinell aus.
Das mit dem Rückgabewert von void hast Du natürlich recht. Ich habe ausversehen eine andere ähnliche Funktion gemeint, da gebe ich einen int zurück....
Gruß
andy_mann
-
Hi andy_mann,
um mal zum Anfang zurückzukommen. Du verwendest einen Vektor suchst darin immer nach einem Wert und bist auf der Suche nach Geschwindigkeitverbesserung.
1.) Verwende einen Container der die Suche bezüglich Schlüssel unterstützt Map oder Set.
2.) Sortiere deinen Vektor nachdem du ihn eingelesen hast, bevor du mit deinen Suchen beginnst. Dann kann man mit binary_search() arbeiten was allemal schneller als ne sequentielle Suche ist.mfg JJ