Toon posts:

[C++] csv-bestanden inlezen en samenvoegen

Pagina: 1
Acties:
  • 121 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Situatie:

Er zijn 3 csv-bestanden met de volgende indelingen:

naw.csv (nummer;naam;straat;postcode;plaats)
oudnummer.csv (nummer;oudnummer)
bank.csv (nummer;banknaam;bankrekening)

Deze drie bestanden moeten uiteindelijk als een text-bestand in de volgende indeling eruit komen:

debiteur.txt (nummer;oudnummer;naam;plaats;bankrekening)

Tot nu toe heb ik het volgende:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>

using namespace std;

int main()
{
     ofstream uitvoer( "debiteur.txt" );

     ifstream in("naw.csv");
     vector < vector <string> > data;
     string element, delimiters = ";\n\r";
     int row = 0;
     char ch;

     data.push_back( vector <string>() );

     while( in.read( (char*)&ch, 1 ) )
     {

          if( delimiters.find_first_of(ch) == delimiters.npos )
          {
               element += ch;
          }
          else
          {
               if( ch != '\r' )
               {
                    data[row].push_back( element );
                    element = "";

                    if( ch == '\n' )
                    {
                         data.push_back( vector <string>() );
                         row++;
                    }
               }
          }
     }

     if( element.size() > 0 )
          data[row].push_back( element );

     in.close();

     for( unsigned int x = 0; x < data.size(); x++ )
     {
          for( unsigned int y = 0; y < data[x].size(); y++ )
          {
                 //................................
          }
     }

     return 0;
}


Op de //...... doe ik dus wat met de data die ik uitlees uit naw.csv. Ik zit alleen vast.

Als ik bijvoorbeeld bij data[0][1] aankom (het eerste nummer) dan wil ik daar graag het oude nummer uit bestand oudnummer.csv bij hebben.

Ik heb zelf al een formule gemaakt die het bestand oudnummer afloopt op zoek naar nummer en het oude nummer retourneert, maar dit is heeeeel erg traag aangezien het gaat om meer dan 22000 debiteuren. (dan zou hij voor iedere debiteur weer een bestand met 22000 regels af moeten lopen, vandaar de traagheid)

Kan iemand een voorzet geven?

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

zoek eens op de verschillende sorteermethodes die bestaan, en op binary search...

ASSUME makes an ASS out of U and ME


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Zijn beide bestanden niet gesorteerd? Dan zou je 'm met een "balanced line" op kunnen lossen.
Heb verder niet naar je code gekeken, alleen even kort naar je probleem

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

Topicstarter
Alle bestanden (dus ook de arrays) staan al gesorteerd op nummer.
Ik heb nu alleen geen idee hoe ik een 2d array dan sorteer maar dan beginnend met bijvoorbeeld nummer 1524 als value die in de array oudnummer bijvoorbeeld op positie oudnummer[1687][0] staat.

Ik moet dus de array oudnummer[][] sorteren, zodat waarde 1524 bovenaan komt te staan?
Daarna kan ik dus de waarden eruit halen?

oudnummer[1687][0] = 1524; //het huidige nummer
oudnummer[1687][1] = 12; //het oude nummer

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Het is toch de bedoeling dat je beide bestanden compleet samenvoegd? En zijn ze daarbij beide gesorteerd op het huidige nummer? In dat geval kan je gewoon in één while-loop door beide bestanden heenwandelen, en ze samenvoegen wanneer ze matchen of degene ophogen die achterloopt. Maar misschien begrijp ik je probleem niet goed...

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12 14:13
Het zou wel erg dom zijn om oudnummer.csv in te lezen in een vector<vector<string> >. De logische structuur is een map<string,string> (nog beter <int, int> maar dan moet je dat structureel doen)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
riezebosch schreef op donderdag 28 juli 2005 @ 07:09:
Het is toch de bedoeling dat je beide bestanden compleet samenvoegd? En zijn ze daarbij beide gesorteerd op het huidige nummer? In dat geval kan je gewoon in één while-loop door beide bestanden heenwandelen, en ze samenvoegen wanneer ze matchen of degene ophogen die achterloopt. Maar misschien begrijp ik je probleem niet goed...
Ze moeten inderdaad samengevoegd worden.
Maar hoe wil je in één while loop door 2 bestanden lopen en uit bestand 2, 1 element in de data array van bestand 1 toevoegen als ze matchen, zonder dat het enorm traag wordt met meer dan 22000 debiteuren?

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Even iets totaal anders:

Mocht dit gewoon een eenmalig iets zijn, is het dan niet een stuk makkelijker om elk van de 3 csv-bestanden in een Access-tabel te gooien en ze met een query te joinen? Scheelt je een hoop code en hoofdbrekens denk ik ;)

Verwijderd

Topicstarter
Helaas, niet éénmalig. Dit moet iedere dag plaats gaan vinden.

Maar ondertussen heb ik de oplossing al. Degene die MSalters aankaartte.
Eerst heb ik het bestand met oude nummers ingelezen en die inderdaad in een
map <string, string> = oud; gezet.
Deze waarde roep ik dan weer aan met oud[huidignummer] = oudnummer.

Werkt perfect.

Bedankt voor de voorzetten....

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Maar met die oplossing moet huidignummer wél een aaneengesloten reeks zijn. Wat mijn hint betreft: met een balanced-line doorwandel je eenmalig beide bestanden tegelijkertijd. De operatie is dus O(n).

Beetje volgens onderstaand idee. Ik heb gelijk structs aangemaakt van de objecten die je hebt, dat werkt een stuk makkelijker (kan ook met classes natuurlijk). Het is geen echte C++ code, maar het idee moet denk ik vrij duidelijk zijn.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
struct Debiteur
{
   int nummer;
   int oudnummer;
   string plaats;
   string bankrekening;
}

struct NAW
{
   int nummer;
   string naam;
   string straat;
   string postcode;
   string plaats;
}

struct Oudnummer
{
   int nummer;
   string oudnummer;
}

// Hier zal je de echte C++ manier voor moeten implementeren
NAW n = fileNaw.read();
Oudnummer o = fileOudnummer.read();

while (!fileNaw.EOF)
{
  // Deze twee while-loops zijn de zogenaamde balanced-line.
  // Het is als een soort horizontale lijn die synchroon door beide bestanden geschoven wordt.
  while (n.nummer < o.nummer)
     n = fileNaw.read();

   while (o.nummer < n.nummer)
      o = fileOudnummer.read();

   if (n.nummer == o.nummer)
   {
      Debiteur d;
      d.nummer = n.nummer;
      d.oudnummer = o.oudnummer;

      vector.push_back(d);
   }
}


offtopic:
Modjes: als zoiets niet de bedoeling is, laat het dan even weten

[ Voor 78% gewijzigd door riezebosch op 28-07-2005 13:58 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

riezebosch schreef op donderdag 28 juli 2005 @ 13:46:
Maar met die oplossing moet huidignummer wél een aaneengesloten reeks zijn. Wat mijn hint betreft: met een balanced-line doorwandel je eenmalig beide bestanden tegelijkertijd. De operatie is dus O(n).

Beetje volgens onderstaand idee. Ik heb gelijk structs aangemaakt van de objecten die je hebt, dat werkt een stuk makkelijker (kan ook met classes natuurlijk). Het is geen echte C++ code, maar het idee moet denk ik vrij duidelijk zijn.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
struct Debiteur
{
   int nummer;
   int oudnummer;
   string plaats;
   string bankrekening;
}

struct NAW
{
   int nummer;
   string naam;
   string straat;
   string postcode;
   string plaats;
}

struct Oudnummer
{
   int nummer;
   string oudnummer;
}

// Hier zal je de echte C++ manier voor moeten implementeren
NAW n = fileNaw.read();
Oudnummer o = fileOudnummer.read();

while (!fileNaw.EOF)
{
  // Deze twee while-loops zijn de zogenaamde balanced-line.
  // Het is als een soort horizontale lijn die synchroon door beide bestanden geschoven wordt.
  while (n.nummer < o.nummer)
     n = fileNaw.read();

   while (o.nummer < n.nummer)
      o = fileOudnummer.read();

   if (n.nummer == o.nummer)
   {
      Debiteur d;
      d.nummer = n.nummer;
      d.oudnummer = o.oudnummer;

      vector.push_back(d);
   }
}


offtopic:
Modjes: als zoiets niet de bedoeling is, laat het dan even weten
Ik denk dat je beter pseudocode had kunnen gebruiken of in tekst uitleggen, nu kauw je het wel een beetje voor..

Trouwens, het begin en het einde van het CSV bestand moeten ook nog gedecteerd worden...

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Verwijderd schreef op donderdag 28 juli 2005 @ 14:15:
[...]
Ik denk dat je beter pseudocode had kunnen gebruiken of in tekst uitleggen, nu kauw je het wel een beetje voor..

Trouwens, het begin en het einde van het CSV bestand moeten ook nog gedecteerd worden...
Wilde ook weer niet alles voorkouwen. Heb het ook beetje bedoeld als pseudo-code. Soort pseudo-pseudo-code dus B)

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12 14:13
riezebosch schreef op donderdag 28 juli 2005 @ 13:46:
Maar met die oplossing moet huidignummer wél een aaneengesloten reeks zijn.
Nee, natuurlijk niet. map is een associatieve array, die mag rustig "gaten" hebben. Hoe groot is het "gat" tussen keys "1" en "10" uberhaupt? (Niet "9" natuurlijk :P)

Ook deze oplossing is natuurlijk O (N log N) in geheugenaccess en O(N) in disk access.

[ Voor 34% gewijzigd door MSalters op 28-07-2005 17:38 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1