Toon posts:

[Python] van 2 lussen 1 maken

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

Verwijderd

Topicstarter
Hoi,

Ik zit met het volgende probleem: ik programmeer afwijkend met Python en dan wel taalgericht. Daarom zit ik nu vast met mijn programma. Dit is het stukje waar het mis gaat bij mij:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for wrd in l[:-1]:
       g.write(wrd + '\t - \n')
g.write(l[-1] + '\t B \n')


for wrd in l:
# eerst de punctuatie van woord afhalen.
        punc = ''
        while wrd[-1] in punctuatie:
                 punc += wrd[-1]
                 wrd = wrd[:-1]
# er moet iets geschreven worden als er geen punctuatie is
        if not punc:
                punc = '*'
g.write(wrd + '\t' + punc + '\n')

Even korte uitleg over het programma:
Het stukje wat je niet ziet zet ieder woord uit een zin op een andere regel. De eerste for-lus zet achter woorden of het een breuk is ja (B) of nee (-) (dit heeft te maken dat je bij bijv. een punctuatie een breuk krijgt).

Maar nu staan de woorden en de punctuatie nog vast aan elkaar en die moeten dus los van elkaar komen. Dat doet de lus met: for wrd in l

Deze 2 doen het nu prima los van elkaar, maar moet dus 1 lus worden. Ik heb via het net begrepen dat dat via 'range' kan, maar hoe moet ik dit dan doen? Omdat ik geen cijfers heb...

Ik hoop dat iemand me kan helpen!!

PS Zie nu dat ik de tabs er niet inkrijg, maar een python-progger weet wel waar de tabs horen te staan.

[ Voor 5% gewijzigd door gorgi_19 op 16-08-2004 18:10 ]


  • klinz
  • Registratie: Maart 2002
  • Laatst online: 21-05 09:01

klinz

weet van NIETS

Verwijderd schreef op 16 augustus 2004 @ 18:02:
PS Zie nu dat ik de tabs er niet inkrijg, maar een python-progger weet wel waar de tabs horen te staan.
Tip: [code]-tag :-)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Misschien is dit een goed moment om de Python tutorial door te nemen en als je hier wilt posten, eerst de beleidsregels door te lezen.

Verwijderd

Ik wil je best helpen, maar ik snap er niet veel van.

Misschien is het makkelijker als je even beschrijft wat de invoer van je programma is, en wat de gewenste uitvoer is. Want uit je code nu kom ik niet echt wijs... (en ik heb het idee dat het ook veel makkelijker kan)

Verwijderd

Topicstarter
@Soultaker: ben je hier mod of wat? Want ik vind je een beetje een rare opmerking maken. Denk je nu echt dat ik niet van het bestaan van die url af wist? En daarnaast heb ik nog uitstekende boeken over Python, zoals het hele dikke boek 'Programmeren in Python' van Mark Lutz. En zoals je al had kunnen lezen: ik ben afwijkend bezig met letters en NIET met cijfers...

@OneOfBorg: ik hoop dat je me kunt helpen! Dit is namelijk voor mijn scriptie en ik wil graag verder, omdat ik er teveel tijd mee aan het verliezen ben.

De input zijn teksten die html-tags bevatten:
<node ID=1 PARENT=5001 RELNAME=span> De volkstelling in China is met vijf dagen verlengd.</node>
<node ID=2 PARENT=1 RELNAME=elaboration-additional> Die had vrijdag moeten eindigen.</node>

Hier is mijn script wat ik tot nu toe heb:
Python:
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
#!/usr/bin/env python

from sys import argv
import sys
import string

def breuk(infn, outfn):
    f = open(infn)
    g = open(outfn , 'w+')
    punctuatie = [".",",",":",";","!","?"]
    for l in f:
            if l.startswith('<node'):
                # Eerst uitvinden vinden waar '<node ... >' ophoudt
                # door te zoeken de positie van naar '>'
                # Daar tel je dan nog 1 bij op, dan ben je er aan voorbij.
                i = l.find('>') + 1
                # Nu knip je dat eerste stuk van de regel
                l = l[i:]
                # Nu nog uitvinden waar '</node>' begint.
                j = l.find('<')
                # ALs laatste haal je spaties aan begin en einde nog weg
                l = l[:j]
                l = l.strip()
                l = l.split(' ')
                # l bevat 1 regel van tekstbestand. Door deze split komt er
                # bij iedere spatie een breuk, die worden opgeslagen in lijst 1

                for wrd in l[:-1]:
                        g.write(wrd + '\t - \n')
                g.write(l[-1] + '\t B \n')


                for wrd in l:
                # eerst de punctuatie van woord afhalen.
                        punc = ''
                        while wrd[-1] in punctuatie:
                                punc += wrd[-1]
                                wrd = wrd[:-1]
                        # er moet iets geschreven worden als er geen punctuatie is
                        if not punc:
                                punc = '*'
                g.write(wrd + '\t' + punc + '\n')

breuk (argv[1], argv[2])


Mijn ouput ziet er als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
De       -
volkstelling     -
in       -
China    -
is       -
met      -
vijf     -
dagen    -
verlengd.        B
verlengd        .

Door het laatste woord 'verlengd' zie je dat dit 2 lussen zijn. Maar hij leest wel over de * heen. Ik had wel iets gevonden wat me erg had geholpen als ik met cijfers aan het programmeren ben. Dit kun je, denk ik, wel vergelijken met wat ik heb.

Twee lussen:
Python:
1
2
for i in range(3):
      print i

Python:
1
2
for j in range(4,7):
    print j

Dit kun je in elkaar schuiven als:
Python:
1
2
3
for i in range(3):
     print i,
     print i + 3

Ik weet dus alleen niet hoe ik zoiets moet aanpakken om dat om te zetten naar wat ik heb.

Dus als je me kunt helpen, dan ben ik je eeuwig dankbaar!!

[ Voor 8% gewijzigd door Verwijderd op 17-08-2004 14:40 ]


  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Ik weet niet zo veel van Python af, maar volgens mij is je eerste for loop gewoon anders dan de tweede:

eerste: for wrd in l[:-1]:

tweede: for wrd in l:

Dus dan is het logisch dat ie niet 2 keer over hetzelfde loopt. Ik snap verder ook niet wat je probleem nu is, want je kunt dit gewoon gewoon oplossen met nested loops. Het range voorbeeldje met getallen dat je laat zien is alleen een optimalisatie maar is geen magische dubbele loop constructie ofzo. Wat verder ook handig zou zijn is leesbare variabele namen. Ik zou ook niet de variabele die je voor je for loop gebruikt binnen de loop zetten met een nieuwe waarde, dit is echt heel verwarrend.

Ik denk dat als je dit allemaal aanpast _en_ je hebt de Python tutorial echt doorgenomen dat je er dan prima uit zelf uitkomt, het is tenslotte jouw scriptie dus je moet nog wel een beetje zelf doen. :)

Verwijderd

Rosey, je hebt volgens mij niet helemaal gelezen wat klinz opgemerkt had: Gebruikt alsjeblieft de [code] tag als je code in je post verwerkt, dat is stukken makkelijker te lezen dan je tekst er direct in plakken (die door HTML formatting helemaal verpoept wordt).

Verder gaf je de output die je nu hebt, terwijl ik je vroeg naar de output die je wou hebben.

Voor zover ik het nu kan zien, wil je elk woord op een eigen regel, en erachter eventuele punctuatietekens aan het einde van het woord, en een - als er geen punctuatietekens waren.

Right:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# De volgende code retourneert een mooie datastructuur 
# waar we eventueel mee verder kunnen werken
#
def singleword(word):
    nopunc = word.rstrip('.,:;?!')
    punct = word[len(nopunc):] or '-'
    return (nopunc, punct)  

def wordbreak(text):
    parts = text.split()
    return [singleword(p) for p in parts]

#
# Deze methode beeldt de datastructuur af 
# zodat we kunnen controleren of de code werkt
# 
def niceprint(seq):
    for item in seq:
        print "%s\t%s" % item

# En een test om te zien of de code werkt
niceprint(wordbreak('De keizer van China draagt kleren. Echt waar? Ja echt.'))


Levert op:

code:
1
2
3
4
5
6
7
8
9
10
De      -
keizer  -
van     -
China   -
draagt  -
kleren  .
Echt    -
waar    ?
Ja      -
echt    .


In Python kun je erg mooie functioneel-achtige constructies maken, dus ik raad je aan die zoveel mogelijk te gebruiken. Imperatieve lussen zijn uit, declaratieve lussen zijn in! B)

[ Voor 15% gewijzigd door Verwijderd op 16-08-2004 20:11 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Verwijderd schreef op 16 augustus 2004 @ 19:26:
@Soultaker: ben je hier mod of wat? Want ik vind je een beetje een rare opmerking maken. Denk je nu echt dat ik niet van het bestaan van die url af wist? En daarnaast heb ik nog uitstekende boeken over Python, zoals het hele dikke boek 'Programmeren in Python' van Mark Lutz. En zoals je al had kunnen lezen: ik ben afwijkend bezig met letters en NIET met cijfers...
Ik ben geen mod, maar net als OneOfBorg kan ik je pas helpen als je je probleem duidelijk formuleert. Daarvoor is het nodig dat je een minimale basis hebt en de postregels op het forum hanteert. Code geschreven in een whitespace-sensitive taal moet simpelweg in code-tags geplaatst worden om redelijkerwijs leesbaar te zijn. Is het zo raar dat ik je vraag om deze minimale moeite te nemen om je vraag helder te presenteren?

klinz wees je al op het bestaan van de [code]-tag. gorgi_19 gaf al het goede voorbeeld door de [code]-tags in je topicstart te editen. Ik verwees je naar de QuickStart waar dit soort dingen ook in staan. Je geeft aan die gelezen te hebben. Toch gebruik je die tags niet. Zolang jij weigert je de kleine moeite te nemen om je code te omsluiten met [code]-tags weiger ik je te helpen en om je daar op te wijzen hoef ik naar mijn idee geen moderator te zijn.

[ Voor 4% gewijzigd door Soultaker op 16-08-2004 20:42 ]


Verwijderd

Topicstarter
@Soultaker: ja, ik had net mijn bericht verstuurd toen ik erachter kwam dat ik de codes vergeten was, mijn excuses! Helaas kun je hier niet meer editen (kon dat iig niet vinden), anders had ik dat meteen recht gezet.

@OneofBorg: dat ziet er heel anders uit. Ik heb Python geleerd via Learing Python van Mark Lutz en David Ascher en die hanteren dan nog de oude stijl in het boek, denk ik. Ik ga morgen eens uitgebreid naar je code kijken. Alvast heel erg bedankt!

Maar nu nog over mijn output. Je hebt gelijk, ik moet nauwkeuriger worden in mijn formuleren. In deze script moet ook een kolom komen die aangeeft of er een breuk komt. Het is nu even een te lang verhaal over het waarom, maar als je dat per se wilt weten, dan hoor ik het wel.
Die breuk staat nu gelijk aan de punctuatie. Dus dat er dan een kolom naast komt te staan, bijv:
code:
1
2
3
hij      -   -
liep     -   -
weg      .   B


En ik dacht, omdat mijn 2 losse loops op zich wel werkte, dat ik nog maar een kleine handeling hoefde te verrichten om er een goed draaiende script van te maken. Alleen weet ik echt niet hoe en vandaar dat ik dit op het forum ben gaan vragen.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Verwijderd schreef op 17 augustus 2004 @ 00:29:
Helaas kun je hier niet meer editen (kon dat iig niet vinden), anders had ik dat meteen recht gezet.
Eerste knopje boven je bericht: Afbeeldingslocatie: http://gathering.tweakers.net/global/templates/got/images/icons/edit.gif ;)

Verwijderd

Verwijderd schreef op 17 augustus 2004 @ 00:29:
Maar nu nog over mijn output. Je hebt gelijk, ik moet nauwkeuriger worden in mijn formuleren. In deze script moet ook een kolom komen die aangeeft of er een breuk komt.
Nou, dat is tamelijk triviaal (en met deze datastructuur misschien zelfs overbodig?).

Je krijgt een lijst van tupels terug; van die tupels is het tweede element de eventuele punctuatie, of een - als er geen punctuatie was. Dat betekent dat jouw gewenste "derde kolom" een '-' is als het tweede element van de tupel een - is, of een 'B' als dat niet zo is.

Dus je zou je code daarop al in kunnen richten: test op een '-' in het tweede element van de tupel. Mocht je persé de uitvoer willen die je aangaf, dan is de volgende generator een optie:

Python:
1
2
3
4
5
6
def transamorgrifyflaboober(seq):
    for (word, punct) in seq:
        if punct == '-':
            yield (word, punct, '-')
        else:
            yield (word, punct, 'B')


Als je deze loslaat op de sequence die je terug krijgt uit wordbreak, dan maakt hij daarvan een sequence die hetzelfde is, maar aan elk tupel nog een element toegevoegd volgens de voorwaarde.

[ Voor 14% gewijzigd door Verwijderd op 17-08-2004 03:54 ]


Verwijderd

Topicstarter
@Soultaker: gevonden! Ik was gister niet ingelogd en dus kon ik dat ook niet vinden :o Maar ik heb het inmiddels gewijzigd.

@OneofBorg: ik weet dat dit heel triviaal overkomt, omdat nu de output min of meer gelijk is. Maar het is de bedoeling dat er een reeks kenmerken aan woorden komen te hangen. Er komt nog een script wat dadelijk aangeeft wat voor soort woorden het zijn, zoals lidwoord, zelfstandig naamwoord, bijvoegelijk naamwoord, etc.

Ik heb nu ook al een scriptje die uitgebreider aangeeft wat nog meer breuken zijn in zinnen. Want niet alleen punten/uitroeptekens/vraagtekens aan het einde van een zin zijn breuken, maar ook een komma in een zin gevolgd door een voegwoord (oftewel: discourse markers). Ik kan het nog verfijnder uitleggen, maar dan kom ik teveel in de tekstwetenschap en dat is nu even niet relevant.

Dit is het andere scriptje, wel even ingekort met minder discourse markers.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python

# voegt een kolom toe met een discourse marker kenmerk

from sys import stdin
from string import join

discourse_markers = ["en", "alsmede", "alsook", "maar", "doch", "of", "dan", "want"]

for l in stdin:
    # pak het woord uit het 1e kolom
    cols = l.split()
    # verander alle hoofdletters naar kleine letters (lower case)
    word = cols[0].lower()
    # bekijk of het een discourse marker is
    if word in discourse_markers:
        feat = '+'
    else:
        feat = '-'
    # voeg in als 2e kolom
    print cols[0], feat, join(cols[1:])


Met dit scriptje geef ik dus aan waar de discourse markers zijn. Dan kun je uiteindelijk vergelijken of de breuken goed staan of dat er te weinig breuken zijn. Of dat ik teveel discourse makers gebruik en dat moet inkorten. Maar dat is dus van latere zorg. Uiteindelijk wordt dit een machine learning programma.

Ik hoop nu dat je beter begrijpt waar dit heen gaat.

Verwijderd

Ik denk het wel... (een beetje toch :)).

Hoewel je in je post niet echt meer een probleem hebt volgens mij, wil ik je nog een paar opmerkingen geven over je Python code:
  • Probeer zoveel mogelijk met een "datastructuur" te werken. Bouw deze op, verander hem, etc. etc., en doe pas op het eind aan afbeelden. Als je straks namelijk moet gaan testen of een woord eindigt op een komma, en dan of het volgende woord een discourse marker is, is dat makkelijker op een lijstje van tuples te doen, dan om uitvoer of een file te gaan parsen.

    En als elk woord heel veel attributen kan bevatten, dan loont het misschien zelfs wel de moeite om er een klasse van te maken, en daar een lijst van bij te houden.
  • Ik zie dat je functies uit de string module gebruikt. Het gebruik daarvan is deprecated: het is de bedoeling dat je de methoden van het string object gaat gebruiken. Dus de code van je join zou worden:

    Python:
    1
    
    " ".join(cols[1:])


    (Ja ik weet het, het ziet er een beetje raar uit, maar dat is ff wennen)
Veel succes verder, en als je nog vragen of problemen hebt, geneer je dan niet om een gil te geven ;)
Pagina: 1