Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: OPGELOST Python probleempje  (gelezen 2527 keer)

Offline BaukeP

  • Lid
OPGELOST Python probleempje
« Gepost op: 2012/02/14, 23:51:52 »
Hallo,

Ik ben op m'n ouwe dag druk aan het experimenteren met python. En dat lukt meestal wel aardig.
Maar het volgende wil niet en ik zie het even niet meer, vandaar graag wat hulp.

Ik ben een csv bestand van de bank aan het omzetten naar een bestand wat ik in mijn MySQL base kan laden. Ik heb hiervoor (met dank Caspar!) het progje van Caspar Verhey gebruikt en het aangepast aan mijn wensen. En dat ging goed, maar was een waslijst met if's en ik dacht dat dat beter moest kunnen.

De code:    for row in inputReader:

        regels = ['Auto','Brandstof auto',' tinq ',' shell ',' tank s ',' dap ',' slump oil ','q8 ','brand oil',' bp lemmer '],
        ['Huishouden','Boodschappen',' poiesz ',' spar ','super de boer','c 1000',' aldi ',' albert heyn ','breimer ',' keurslager',' bakkerij ']
        
        for i, item in enumerate(regels):
            for t, zoekterm in enumerate(regels[i):
                if( zoekterm in str(row[7]).lower()):
                    in_rubriek  = regels[i,0]; in_grootboek  = regels[i,1]

        uit_row = [ uit_datum, uit_reknr, uit_begunstigde, uit_tegenrek, uit_bedrag, uit_code, uit_rubriek, uit_grootboek , uit_omschrijving]
        outputWriter.writerow(uit_row)

Ik loop hierbij alle regels van het csv bestand door en wil vervolgens per regel een woord zoeken uit 'regels' (index 2:). Indien gevonden worden velden met index 0 en 1 toegevoegd.

Dus ik zoek iedere regel achtereenvolgens door voor bijv. tinq en shell etc en indien gevonden wordt Auto en 'Brandsof auto' toegevoegd.

Het stukje code met de for etc. is het probleemstukje.

Wie ziet waar deze hobbyist fout gaat?

Alvast bedankt

Bauke de Vries
« Laatst bewerkt op: 2012/02/29, 08:35:55 door BaukeP »

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #1 Gepost op: 2012/02/15, 12:00:15 »
Vervolg:

Dit doet het beter, maar loopt niet alle regels door (eerste for)

        for index in range(len(regels)):
            totaal = regels[index]; bestemming = totaal[:2]; zoekterm = totaal[2:]
            for i in range(len(zoekterm)):
                if( zoekterm in str(row[7]).lower()):
                    in_rubriek = bestemming[0]; in_grootboek = bestemming[1]

Iemand een oplossing?

Bauke

Offline MKe

  • Lid
Re: Python probleempje
« Reactie #2 Gepost op: 2012/02/15, 14:44:56 »
Je zegt dat je een probleem hebt, maar het is me niet duidelijk welk probleem je hebt. Maar misschien snap ik je doelstelling niet?

Klopt dit wel:
Citaat
Dus ik zoek iedere regel achtereenvolgens door voor bijv. tinq en shell etc en indien gevonden wordt Auto en 'Brandsof auto' toegevoegd.


Maar even dat erbuiten gelaten een paar vraagjes over je eerste script.
Waarom wordt variabele "regels" opnieuw ingesteld bij elke keer dat de loop wordt doorlopen?
de regel:
for t, zoekterm in enumerate(regels[i):moet volgens mij zijn:
for t, zoekterm in enumerate(regels[i]):
Als je per regel wilt kijken of 1 van de woorden van regel in een gelezen row zit moet je volgens mij iets als dit doen:
regels = {
            'Auto':'Huishouden',
            'Brandstof auto':'Huishouden',
          ' tinq ':' poiesz ',
            }
          
for row in inputReader:
    for word in regels.keys():
        if word in row.lower():
             doe iets wat je zelf wilt
« Laatst bewerkt op: 2012/02/15, 14:48:05 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #3 Gepost op: 2012/02/16, 00:10:12 »
Opgelost!

regels = [['Auto','Brandstof auto',' tinq ',' shell ',' tank s ',' dap ',' slump oil ','q8 ','brand oil',' bp lemmer '],
        ['Huishouden','Boodschappen',' poiesz ',' spar ','super de boer','c 1000',' aldi ',' albert heyn ','breimer ',' keurslager',' bakkerij ']]

Een extra set [] deed het!

Bauke

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #4 Gepost op: 2012/02/16, 00:13:07 »
MKe,

Naar dat opnieuw instellen ga ik kijken. Het grootste probleem was de syntax van een geneste list.

Bauke

Edit: Ik zie nu dat je codes gelijk zijn!

Edit2: Het betreffende stukje is nu zo: (m.i. iets netter)

for index in range(len(regels)):
            bestemming = regels[index][:2]; zoekterm = regels[index][2:]
            for i in range(len(zoekterm)):
                if( str(zoekterm[i]).lower() in str(row[7]).lower()):
                    in_rubriek = bestemming[0]; in_grootboek = bestemming[1]
« Laatst bewerkt op: 2012/02/16, 00:18:54 door BaukeP »

Offline MKe

  • Lid
Re: Python probleempje
« Reactie #5 Gepost op: 2012/02/16, 08:29:44 »
Hoi,

Ah ik snap nu eindelijk wat je wilt doen. Ik moet echt leren lezen :)
Voor nog mooier zou je het misschien zo kunnen doen:
regels = [
          {'rubriek':'Auto',
           'grootboek':''Brandstof auto',
          'zoekterm':[' tinq ',' shell ',' tank s ',' dap ',' slump oil ','q8 ','brand oil',' bp lemmer ']},
          
          {'rubriek':'Huishouden',
          'grootboek':'Boodschappen',
          'zoekterm':[' poiesz ',' spar ','super de boer','c 1000',' aldi ',' albert heyn ','breimer ',' keurslager',' bakkerij ']},
           ]
for row in inputReader:
    for regel in regels:
        for zoekterm in regel['zoekterm']:
            if str(zoekterm).lower() in str(row[7]).lower():
                in_rubriek = regel['rubriek']
                in _grootboek = regel['grootboek']

Op die manier heb je meer structuur in je regels en is het ook makkelijker te snappen wat je eigenlijk doet omdat je index een omschrijvend woord is. Dit maakt het een stuk leesbaarder als je er later nog eens naar kijkt. Ook voor een buitenstaander als ik is het dan gemakkelijker te lezen wat je doet i.p.v. met al die genummerde indices. Het scheelt ook een hoop extra variabelen.
Zie ook hoe ik 'regels' declareer buiten de loop. Op die manier wordt dit maar 1 keer gedaan in plaats van bij elke iteratie.

tip: Er is trouwens in Python een methode om lists met elkaar te vergelijken m.b.v. sets. Die zou je misschien ook kunnen gebruiken en hoef je niet steeds de zoektermen te doorlopen. Dit vereenvoudigd het scriptje nog meer, maar daar moet je zelf maar eens naar zoeken.
« Laatst bewerkt op: 2012/02/16, 08:32:05 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #6 Gepost op: 2012/02/21, 18:23:44 »
MKe,

Bedankt. We leren dagelijks!

Bauke

Re: Python probleempje
« Reactie #7 Gepost op: 2012/02/22, 00:27:27 »
Dit:
            if str(zoekterm).lower() in str(row[7]).lower():kan gewoon
            if zoekterm in row[7].lower():worden.
Zoektermen zijn als lowercase string opgegeven en csv.reader geeft altijd een string als resultaat. Dit is misschien meer een kwestie van smaak, maar als ik zelf een lijst van strings moet opstellen, gebruik ik geen whitespaces. Zeker zo willekeurig als hierboven kan tot fouten leiden. Maak gewoon een list van strings aan en strip de whitespace van de gezochte woorden. Dat word dan:
            if zoekterm in row[7].strip().lower():
Misschien ook een 'break' zetten als de in_rubriek en in_grootboek gevonden zijn. Het is niet nodig om verdere zoektermen te zoeken als het resultaat al gevonden is.

Offline MKe

  • Lid
Re: Python probleempje
« Reactie #8 Gepost op: 2012/02/22, 09:48:27 »
Op zich is het verstandig om de zoekterm ook in lower om te zetten voor het geval je een fout hebt gemaakt bij het invoeren van de zoekterm.

En als je dan toch bezig bent kan het nog veel sneller om de zoekterm te zoeken:
for row in inputReader:
    for regel in regels:
        if set( regel['zoekterm'] ) & set( row[7].lower().split() ):
            in_rubriek = regel['rubriek']
            in _grootboek = regel['grootboek']

De "set()&set()" statement geeft waar als er overeenkomstige items in de twee lijsten zitten. Scheelt weer een nested loop.


« Laatst bewerkt op: 2012/02/22, 10:42:40 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #9 Gepost op: 2012/02/23, 20:11:50 »
Heren bedankt!

@Nunslaughter: Ik ben inderdaad begonnen met kleine letters in de zoekstring. Daarna kwam ik tot ontdekking dat het kopieren (en vervolgens plakken in het script) van een nieuwe zoekstring (uit het bankbestand) veel gemakkelijker is. Van daar dat ik die beide lower's laat staan.
De break heb ik toegevoegd.

@MKe
Sets heb ik nog geen ervaring mee. Ga ik nu uiteraard wel uit proberen.
Vraagje: Hebben de breaks nog nut als ik sets gebruik?

Bauke

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #10 Gepost op: 2012/02/23, 20:25:36 »
@MKe

Je 'set' voorstel geprobeerd. Helaas wordt er geen enkele zoekterm meer gevonden, ook niet als ik de split() weghaal.

Bauke

Offline MKe

  • Lid
Re: Python probleempje
« Reactie #11 Gepost op: 2012/02/23, 20:52:55 »
@MKe

Je 'set' voorstel geprobeerd. Helaas wordt er geen enkele zoekterm meer gevonden, ook niet als ik de split() weghaal.

Bauke
Heb je de spaties wel uit je zoektermen gehaald?
Split() splitst namelijk op lege stukken als spaties, tabs of linefeeds. In principe wordt je string dus opgesplitst in de losse woorden en die worden in een list gezet. Maar die bevatten dus geen spatie meer.
Je hebt bij het gebruik van set ook geen break nodig want de loop mist. Break stopt namelijk een loop.
« Laatst bewerkt op: 2012/02/23, 20:55:20 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #12 Gepost op: 2012/02/23, 22:05:39 »
Oh, is dat het!

Dan geeft de oude methode waarschijnlijk betere resultaten. Er zijn namelijk ook zoekstrings met twee woorden en dat zal gesplitst worden.

Maar ook als ik jouw split() weghaal doet 'ie het niet.

Bauke

Offline MKe

  • Lid
Re: Python probleempje
« Reactie #13 Gepost op: 2012/02/23, 22:20:43 »
Oh, is dat het!

Dan geeft de oude methode waarschijnlijk betere resultaten. Er zijn namelijk ook zoekstrings met twee woorden en dat zal gesplitst worden.

Maar ook als ik jouw split() weghaal doet 'ie het niet.

Bauke
Het klopt dat hij niet werkt zonder split. Deze methode met set werkt alleen met lists en zonder split blijft het een string. Als je zoektermen van 2 woorden gaat gebruiken is dit misschien geen goede methode tenzij je een andere manier van splitsen kunt bedenken. Wel jammer want het is een zeer efficiente methode.
« Laatst bewerkt op: 2012/02/24, 06:43:57 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline BaukeP

  • Lid
Re: Python probleempje
« Reactie #14 Gepost op: 2012/02/23, 22:59:13 »
Oké. Bedankt voor de uitleg. Ben weer iets wijzer geworden.

Bauke