Daten effizient einlesen



  • Warum genau müssen es verschachtelte maps sein?

    Sone schrieb:

    @Werner: Ist das nicht irgendwie bescheuert? 😃

    Nein, die Lösung ist ziemlich gut...

    Sone schrieb:

    Anschließend könnte ja noch die "Fehler beim Lesen" Fehlermeldung kommen. Also fände ich es schlauer, schon noch -1 o.ä. zurückzugeben, wenn die Datei nicht geöffnet werden konnte.

    Ist ja nur ein Beispiel, daran wirds hoffentlich nicht scheitern...



  • dot schrieb:

    Warum genau müssen es verschachtelte maps sein?

    Sone schrieb:

    @Werner: Ist das nicht irgendwie bescheuert? 😃

    Nein, die Lösung ist ziemlich gut...

    ? Natürlich ist sie das. Ich meinte das spezifische das ich Ansprach.
    Und klar, es ist nur ein Beispiel.
    Ich meine nur, wenn etwas schiefgeht, dann sollte das Programm umgehend terminiert werden, und nicht noch warten bis was anderes Schiefgeht oder überhaupt nicht terminieren (bis zum Ende).



  • Sone schrieb:

    @Werner: Ist das nicht irgendwie bescheuert? 😃

    if( !datei.is_open() ) 
                cerr << "Fehler beim Oeffnen" << endl; //Hier ist also datei ein ungültiger Filestream
    Score s; 
    for( int idx1, idx2; datei >> idx1 >> idx2 >> s; ) // <=== hier geschieht das Einlesen, und hier könnte auch mit einem ungültigen Filestream gearbeitet werden
    

    Anschließend könnte ja noch die "Fehler beim Lesen" Fehlermeldung kommen. Also fände ich es schlauer, schon noch -1 o.ä. zurückzugeben, wenn die Datei nicht geöffnet werden konnte.

    .. ja wäre schon schlauer, aber das sind doch Peanuts.

    dot schrieb:

    Sone schrieb:

    @Werner: Ist das nicht irgendwie bescheuert? 😃

    Nein, die Lösung ist ziemlich gut...

    Danke 🙂

    banshee schrieb:

    ... Ich habe beim Einlesen noch hier Probleme

    Werner Salomon schrieb:

    [cpp] for( int idx1, idx2; datei >> idx1 >> idx2 >> s; ) // <=== hier geschieht das Einlesen [/cpp]

    Zunächst mal würde ich die Länge der Daten (also N) gerne auch erst zur Laufzeit einlesen, weil es sich zwischen verschiedenen Dateien unterscheiden kann.

    Es hindert Dich niemand, das N einzulesen, wo steht es denn in der Datei?

    banshee schrieb:

    Und dann ist dieser Operator, um N floats aus dem Stream in ein float-array zu lesen nicht definiert.

    Ist definiert und implementiert in/ab Zeile 11 meines Listings. Sagt Dein Compiler was anderes? Wenn ja - wie heißt der?

    banshee schrieb:

    Auf die multimap kann ich übrigens auch verzichten. Es geht mir im Prizip nur darum, eine (pro Datei) dynamische Anzahl von floats zeilenweise zu lesen und speichern, am liebsten direkt in einem Array.

    .. um es kurz zu machen: poste doch ein Beispiel von 5 oder 6 Zeilen aus so einer Datei und die Datenstruktur, in die Du es hinein haben möchtest und welche Werte wo hin sollen und was sie bedeuten.

    Deine jetzige Aussage steht ein wenig im Widerspruch mit Deinem ersten Posting.
    Ist 'N' die Anzahl der Daten die hinter den ersten beiden Indizes in einer Zeile kommen, oder ist 'N' die Anzahl der Werte in der Datei?
    Sollen alle Werte in eine Array? oder sollen alle Werte einer Zeile in ein Array? Wie unterscheidest Du im ersten Fall zwischen Index und Daten1-N?
    Ist im zweiten Fall in jeder Zeile das N gleich?
    Und wie meinst Du das genau mit dem Aufteilen auf zwei Datensätze? - am besten Du postest mal ein Beispiel.

    Und noch eine Frage, deren Antwort mich wirklich interessiert:

    banshee schrieb:

    Naja, an der Uni haben wir gelernt, sich die Ideen vor dem coden zu machen 😉 ... Ich habe also die Zeilen erst mal als Stringvektor eingelesen, damit ich weiß, wieviele es sind.

    Lernt man das an der Uni?

    Gruß
    Werner



  • Werner Salomon schrieb:

    Es hindert Dich niemand, das N einzulesen, wo steht es denn in der Datei?

    Es steht gar nicht in der Datei, aber lässt sich ja leicht feststellen, indem man einfach einen Datensatz liest.

    Werner Salomon schrieb:

    Ist definiert und implementiert in/ab Zeile 11 meines Listings. Sagt Dein Compiler was anderes? Wenn ja - wie heißt der?

    Hast du das jetzt noch nachträglich reineditiert oder war ich tatsächlich so dämlich und hab das übersehen? 😮

    Werner Salomon schrieb:

    .. um es kurz zu machen: poste doch ein Beispiel von 5 oder 6 Zeilen aus so einer Datei und die Datenstruktur, in die Du es hinein haben möchtest und welche Werte wo hin sollen und was sie bedeuten.

    4006 4006 90.481 100 77.44 99.618 38.218 5.9542 113.85 99.651 98.3 10.84 99.233 0 -7.0489 0 99.569 100 86.302 99.611 40.235 6 113.08 99.879 98.605 6.4638 99.233 0 -7.4525 0 99.848 61 0.76014 0.73971 82 0.69328 0.67477 67 0.727 0.69966 54.409 100 77.44 99.618 38.218 5.9542 113.85 99.651 98.3 10.84 99.233 0 -7.0489 0 99.569 100 64.62 99.385 19.47 6.1085 71.966 96.738 90.803 0.42525 99.233 0 -0.16675 0 95.997 50 0.76014 0.46376 62 0.69328 0.43891 48 0.727 0.51824
    4007 4007 93.473 100 62.947 97.976 50.591 6.1293 117.91 99.955 91.366 4.2724 99.233 0 -5.6845 0 99.945 100 71.978 98.51 57.768 6.1699 118 99.959 88.7 1.6841 99.233 0 -6.2708 0 99.95 47 0.56152 0.46012 52 0.46007 0.43902 60 0.51986 0.50468 55.984 100 62.947 97.976 50.591 6.1293 117.91 99.955 91.366 4.2724 99.233 0 -5.6845 0 99.945 100 32.962 91.89 13.777 5.9542 75.057 99.956 92.572 0.19703 99.233 0 0.85399 0 99.946 66 0.56152 0.48313 54 0.46007 0.44998 63 0.51986 0.51955
    4008 4008 93.256 100 63.255 99.245 96.63 6.0224 110.39 99.95 84.628 27.093 99.233 0 -5.7217 0 99.938 100 63.05 99.256 32.392 6.0444 110.19 99.946 84.728 26.596 99.233 0 -6.2318 0 99.935 40 0.58972 0.5731 48 0.51287 0.46929 48 0.52208 0.54031 12.782 100 63.255 99.245 96.63 6.0224 110.39 99.95 84.628 27.093 99.233 0 -5.7217 0 99.938 19.487 44.135 99.556 26.509 5.9069 45.202 26.245 94.338 0.24401 99.233 31.321 8.8088 0 23.043 22 0.58972 0.40665 39 0.51287 0.33997 35 0.52208 0.40721
    

    ID1_1 ID2_1 Datum1_1 ... DatumN_1
    ...
    ID1_M ID2_M Datum1_M ... DatumN_M

    Ja, das N ist in jeder Zeile gleich.

    In Matlab kann man die gesamten Daten der Datei (abzügl. IDs) schön in eine große Matrix packen und dann einfach über die Indizierung ganze Spalten, Reihen und einzelne Felder extrahieren. Sowas würde ich nach Möglichkeit auch gerne machen.

    Werner Salomon schrieb:

    Lernt man das an der Uni?

    Man kriegt an der Uni selten konkrete Code-Snippets beigebracht, also nein. Das ganze ist eben die schlechte Brute-Force-Variante, die man mangels Zeit (hoffentlich nur) temporär einführt, damit man sich schnell wieder auf das Wesentliche konzentrieren kann.



  • Dann lies doch die erste Zeile ein, zähl die ersten beiden Zahlen nicht mit und du hast dein N, wie es schonmal erwähnt wurde. Dann kannst du mit dem N Werners Beispiel nutzen. Dann musst du nur noch das mit den Permutationen machen.



  • Hallo banshee,

    gar nicht so einfach Dir zu antworten. Erst sollen die Daten in eine map und aufgeteilt werden. Jetzt ist es eine Matrix. Was idx1 und Idx2 sind - bzw. wo die hin sollen - ist nach wie vor unklar.
    Deine Überschrift ist 'Daten effizient einlesen'. Also ein int oder ein float liest man am besten mit dem dazugehörigen Streamingoperator direkt aus der Datei. Und ansonsten bist Du dann effizient, wenn Du als Struktur, in die Du das einliest, gleich die Struktur wählst, die Du später im Programm benötigst - ohne irgendwelche Umwege oder umsortieren. Ergo wenn Du zwei 'zufällig(!) zwei gleichgroße(!) Datensätze' benötigst, warum dann nicht gleich beim Einlesen erzeugen.

    Hier noch mal ein Ansatz, um das ganze in eine Matrix zu lesen. Aber ich glaube, dass das noch nicht der letzte Schuss ist. Beachte bitte auch den Link in der ersten Zeile.

    #include "is_endl.h" // s. <http://www.c-plusplus.net/forum/p1940874#1940874>
    #include <fstream>
    #include <iostream>
    #include <vector>
    #include <limits>
    
    struct DataReader
    {
        DataReader( std::vector< float >& data )
            : data_( &data )
        {}
        std::vector< float >* data_;
    };
    // --   liest soviel Data wie in der Zeile stehen
    std::istream& operator>>( std::istream& in, DataReader l )
    {
        l.data_->clear();
        for( float f; !is_endl( in ) && in >> f; )
            l.data_->push_back( f );
        return in;
    }
    
    int main()
    {
        using namespace std;
        vector< vector< float > > alles;
        {
            ifstream datei("input.txt");
            if( !datei.is_open() )
            {
                cerr << "Fehler beim Oeffnen" << endl;
                return -2;
            }
            int idx1, idx2;
            for( vector< float > line; datei >> idx1 >> idx2 >> DataReader( line ); )
            {
                // ich habe keine Ahnung was Du mit idx1 und idx2 vor hast?
                alles.push_back( line );
            }
            if( !datei.eof() )
                cerr << "Fehler beim Lesen" << endl;
        }
        // Zugriff z.B. über float f = alles[iZeile][iSpalte];
        cout << "\n" << alles.size() << " Zeilen gelesen" << endl;
        return 0;
    }
    

    Gruß
    Werner



  • Werner Salomon schrieb:

    Und ansonsten bist Du dann effizient, wenn Du als Struktur, in die Du das einliest, gleich die Struktur wählst, die Du später im Programm benötigst - ohne irgendwelche Umwege oder umsortieren.

    Das ist ja auch mein Ziel und ich mache auf den Daten später dann noch weitere Berechnungen, wo ein möglichst matlabähnlicher Matrixzugriff wohl am handlichsten wäre. Dort kann man mit demselben Befehl auf:

    a) Felder: mat(1, 2)
    b) Zeilenvektoren: mat(2, 🙂
    c) Spaltenvektoren: mat(:, 3)
    d) sogar ganze Submatrizen: mat([1 5 6], [2 4 9])

    zuzugreifen. All das brauche ich später in den weiteren Berechnungen mal. vector<vector>> ist mir auch als erstes in den Sinn gekommen und in einer Richtung bekommt man damit Zeilen (bzw. Spaltenvektoren je nach alignment) mit einem simplen getter, aber eben nicht die andere Richtung, geschweige denn Submatrizen. Es läuft wieder darauf hinaus, sich diese Zugriffe in Funktionen zu kapseln, in loops durch die Matrix zu laufen und sich neue Submatrizen und Vektoren zu erzeugen.
    Ich hab deinen Code jetzt mal übernommen, programmiertechnisch definitiv interessant und lehrreich, aber um eine Datei mit ca. 22k dieser Zeilen zu lesen (und die größte hat 130k), braucht es schon 1-2 Minuten, während Matlab das in einer Sekunde macht. Des weiteren sind die Matrizen in Matlab dann solange im Workspace bis sie überschrieben werden, d.h. muss nur 1x einlesen und kann den dahinter liegenden Code separat ändern und ausführen. Wenn ich das unter VC++ machen will, muss ich jedes mal neu einlesen oder gibts für sowas eine möglichst simple Serialisierung?



  • banshee schrieb:

    ... und ich mache auf den Daten später dann noch weitere Berechnungen, wo ein möglichst matlabähnlicher Matrixzugriff wohl am handlichsten wäre. Dort kann man mit demselben Befehl auf:

    a) Felder: mat(1, 2)
    b) Zeilenvektoren: mat(2, 🙂
    c) Spaltenvektoren: mat(:, 3)
    d) sogar ganze Submatrizen: mat([1 5 6], [2 4 9])

    zuzugreifen. All das brauche ich später in den weiteren Berechnungen mal. vector<vector>> ist mir auch als erstes in den Sinn gekommen und in einer Richtung bekommt man damit Zeilen (bzw. Spaltenvektoren je nach alignment) mit einem simplen getter, aber eben nicht die andere Richtung, geschweige denn Submatrizen. Es läuft wieder darauf hinaus, sich diese Zugriffe in Funktionen zu kapseln, in loops durch die Matrix zu laufen und sich neue Submatrizen und Vektoren zu erzeugen.

    Du kannst Dir daraufhin mal boost.uBlas anschauen. Ich habe da selber keine Erfahrung mit. Nach eigenen Aussagen sind die Algorithmen in dieser Bibliothek aber sehr schnell.

    banshee schrieb:

    .. um eine Datei mit ca. 22k dieser Zeilen zu lesen (und die größte hat 130k), braucht es schon 1-2 Minuten, während Matlab das in einer Sekunde macht.

    Ich habe mir mal eine Datei erzeugt. mit 22k - also 22000 - Zeilen, pro Zeile 76 floats. Die floats mit jeweils 5Stellen, wie in Deinem Beispiel oben. Die Datei ist dann gut 12MByte groß.
    Ich kann diese mit obigem Code in 8s einlesen. Warum das bei Dir so lange dauert, weiß ich nicht. Ich benutze Visual Studio 2010.

    Gruß
    Werner



  • ich würd mal auf debug mode tippen. 🙂



  • Ja, stimmt. Release dauert auch wenige Sekunden. Trotzdem wird sich meine Entwicklungsarbeit so ganz ohne Debug-Mode als schwierig gestalten. Try-Error ist schließlich das studentische Best Practice No. 1 😛


Anmelden zum Antworten