Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: Taulukon viimeiset sarakkeet uusiksi riveiksi

Ansy [06.10.2013 22:07:11]

#

Tervehdys,

ongelmana on tekstitiedoston datan muokkaus. Tekstitiedosto sisältää viisi saraketta.

1 | 2 | 3 | 4 | 5 |

1 2 4 4 1
2 3 4 4 3
3 4 5 0 0

Tarkoitus olisi siirtää sarakkeiden 4 ja 5 ( arvot > 0 ) sarakkeiden 1 ja 2 yläpuolelle tai jatkoksi:


1 | 2 | 3 | 4 | 5 |

1 2 4 0 0
2 3 4 0 0
3 4 5 0 0
4 1 0 0 0
4 3 0 0 0

Toivoisin ongelmaan vastauksia, eikä suinkaan mitenkään kielisidottuna.

Metabolix [07.10.2013 08:26:41]

#

kun saadaan luettua luvut s1, s2, s3, s4, s5:
	lisää taulukkoon t1 luvut s1, s2, s3, 0, 0
	lisää taulukkoon t2 luvut s4, s5, 0, 0, 0
kun taulukon t2 lopussa on 0, 0, 0, 0, 0:
	poista taulukon t2 viimeinen rivi
tulosta taulukko t1
tulosta taulukko t2

Taulukoksi käy hyvin C++:n std::vector.

Rox [07.10.2013 18:48:52]

#

#include <iostream>
#include <Windows.h>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <fstream>
#include <string>

INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
{
std::vector<std::vector<double> > contents;
{
    std::ifstream Tiedosto( "data.txt" );
    for ( std::string line; Tiedosto; std::getline( Tiedosto, line ) ) {
        std::stringstream line_stream( line );
        std::vector<double> row;
        copy( std::istream_iterator<double>( line_stream ), std::istream_iterator<double>(),
            back_inserter(row) );
        contents.push_back( row );
    }
}
unsigned int Koko = contents.size();
for ( unsigned int i=0; i < Koko; ++i ) {
    std::vector<double> row( 5, 0. );
    bool add_row = false;
    if ( contents[i].size() >= 5 ) {
        for ( unsigned int j=3; j<4; ++j ) {
            double value = contents[i][j];
            contents[i][j] = 0.;
            if ( value > 0 ) {
                add_row = true;
                row[j-3] = value;
            }
        }
        if ( add_row == true ) {
            contents.push_back( row );
        }
    }
}
std::ofstream Uus;
Uus.open("Uusi.txt");
for ( unsigned int i=0; i < contents.size(); ++i ) {
    copy( contents[i].begin(), contents[i].end(), std::ostream_iterator<double>( Uus, " " ) );
    Uus << std::endl;
}
Uus.close();
MessageBox(NULL, "Valmis!", "Valmis", MB_ICONINFORMATION);
ExitProcess(0);
}

@Stackoverflow + pieni muokkaus.

Metabolix [07.10.2013 21:03:38]

#

Tässä on vielä versio, jossa on korjattu eräitä Roxin koodin puutteita: tämä on lyhyempi ja selvempi ja toimii oikein eikä ole riippuvainen Windowsista.

#include <fstream>
#include <vector>
#include <string>

int main() {
	std::string a, b, c, d, e;
	std::vector<std::string> t1, t2;
	for (std::ifstream ifs("in.txt"); ifs >> a >> b >> c >> d >> e;) {
		t1.push_back(a + " " + b + " " + c + " 0 0\n");
		if (d != "0" || e != "0") {
			t2.push_back(d + " " + e + " 0 0 0\n");
		}
	}
	std::ofstream ofs("out.txt");
	for (auto s: t1) ofs << s;
	for (auto s: t2) ofs << s;
}

Ansy [08.10.2013 22:35:46]

#

Kiitoksia vastauksista!

Päädyin tekemän koodin Pythonilla esimerkkienne mukaan. Mitenkäs muuten dataa, joka sisältää paljon numeroita kannattaa säilöä yleensäkkin? Kokeilin huvikseen .txt tiedostoa ja sain yli gigan kirjoittamiseen näköjään uppoaa aikaa kivasti. Tarkoitus olisi vielä käsitellä isoja alueita .txt tiedostosta, joten tämä ei liene järkevää. Pythonia käytän vasta ensimmäistä päivää, joten muista vaihtoehdoista ei ole kokemusta. -> data, tietokanta jne?

Ongelmia tuli vastaan myös lukujen käsittelyissä, koska for looppeja ei voinut käyttää laisinkaan pitkien numerosarjojen takia. (overflow). Onneksi asian pysty kiertää while loopeilla.

Ihastuin kyllä IPythonin (Py 2.7) Notebookkiin :)

Metabolix [08.10.2013 22:53:18]

#

Jos data sisältää pelkästään lukuja, binäärimuoto on selvästi käytännöllisin. Esimerkiksi jos data koostuu viidestä sarakkeesta, joissa on vain pieniä lukuja (alle 256), riittää tiedostossa yksi tavu jokaiselle luvulle. Dataa voi muuttaa binäärimuodon ja tavallisten muuttujien välillä struct-moduulin funktioilla.

Suuren datamäärän käsittelyssä on hyvä huomioida, että Python on selvästi hitaampi kuin esimerkiksi C++ tai Java ja muuttujatkin vievät siinä enemmän tilaa. Gigan kokoinen tiedosto kuulostaa jo sellaiselta, että aika monessa tilanteessa jättäisin Pythonin heti pois laskuista.

Ansy kirjoitti:

Ongelmia tuli vastaan myös lukujen käsittelyissä, koska for looppeja ei voinut käyttää laisinkaan pitkien numerosarjojen takia. (overflow). Onneksi asian pysty kiertää while loopeilla.

Olet varmaankin tulkinnut ongelman väärin; for-silmukassa ei ole mitään erityistä rajoitusta. Python 2:ssa kuitenkin range-funktio luo luvuista listan, joten sitä ei voi käyttää suurten lukualueiden kanssa, koska listasta tulee mahdottoman suuri. Sen sijaan xrange luo iteraattorin, joten sitä voi käyttää suurillakin alueilla. Python 3:ssa range toimii samoin kuin entinen xrange, joten siinä koko ongelmaa ei varmaan olisi ilmennyt.

Yleensä kannattaa käyttää uusinta versiota, jos ei ole erityistä syytä käyttää vanhaa.

Ansy [08.10.2013 23:38:39]

#

Oh ok, kiitos tiedosta! Tosiaan tuli käytettyä range- / xrange-funktiota ja niihin tosiaan kosahti. Koodausmielessä Python tuntuu omasta näkövinkkelistä helpommalta ja selkeämmältä kuin C++. Javaa ei ole tullut paljon kokeiltua, joten se on seuraavana listassa, ellei Pythonilla ala toimimaan kunnolla asiat.

Tietty C++ en ole sulkenut pois mielestä, mutta osaksi rikkinäinen versio visual studiosta tuntuu vaan niin kankealta pyörittää läppärillä. Varmaan pitäisi tutustua ilmaisiin kääntäjiin.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta