DOMANDA Python: aiuto per problema su codice

Giargianas

Nuovo Utente
16
1
Ciao a tutti.

Apro questo thread per chiedere aiuto a chi ne sa di Python.
Espongo il problema:
Sto studiando Python e sono arrivato al capitolo sui dizionari.
Finito il capitolo uno degli esercizi è il seguente:
Exercise 9.2 Write a program that categorizes each mail message by which day
of the week the commit was done. To do this look for lines that start with “From”,
then look for the third word and keep a running count of each of the days of the
week. At the end of the program print out the contents of your dictionary (order
does not matter).
Sample Line:
From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008
Sample Execution:
python dow.py
Enter a file name: mbox-short.txt
{'Fri': 20, 'Thu': 6, 'Sat': 1}
Il file di riferimento è il seguente:
http://www.py4inf.com/code/mbox-short.txt

Ho scritto il seguente codice per cominciare a definire il loop che fa il parsing delle righe:
Codice:
import string

#inserimento file
f = raw_input('enter file:')
p = open(f)
c = p.read()

#dizionario
d = dict()    

for line in c:
    line = line.rstrip()
    #split corretto
    words = c.split()
    line = line.translate(None, string.punctuation)
    #guardian pattern
    if len(words) == 0: continue
    if words[0] != 'From': continue
    
    if words[0] == 'From':
        print words[2]

    for day in c:
        d[day] = d.get(day,0) + 1

print d

Il mio problema è che il loop non rispetta né il guardian pattern né il la condizione necessaria (inizio linea con 'From'), e continua a ritornare e fare riferimento solo e soltanto alla prima linea.
E lo fa per tutte le linee presenti nel file, che sono una marea.

Riporto la risposta quando eseguo il codice in PyCharm:
enter file:mbox-short.txt
Sat
Sat
Sat
Sat
Sat
Sat
Sat
Sat
Sat
Sat

Secondo voi quale può essere il problema?
Come posso risolverlo?

Grazie mille in anticipo per l'aiuto.
 

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
Ci sono 3 errori e 1 imprecisione:
1* p.read() legge il file e costruisce una unica stringa. Quando poi iteri sopra la stringa, succede consideri un singolo carattere alla volta. Non è ciò che vuoi, prova con p.readlines().
2* quando usi split, usalo sulla linea (variabile line), non sull'intero documento (variabile c, che a causa dell'errore 1, è una unica stringa contenente tutto il file, per la quale la terza parola sarà sempre 'Sat')
3* la chiave che usi per scrivere nel dizionario è sbagliata
4* dovresti usare lstrip per togliere gli spazi a inizio riga, rstrip invece li toglie dalla fine (ma tu poi fai split e conti dall'inizio, non dalla fine). In ogni caso, almeno su python 3 (a occhio tu usi il 2, ti consiglierei di andare direttamente sul 3), split() esclude automaticamente gli spazi ripetuti (che sarebbero stringhe vuote) dall'output.

Ricapitolando:
Python:
#inserimento file
f = raw_input('enter file:')
p = open(f)
c = p.readlines()
#dizionario
d = dict()
for line in c:
    words = line.split()
    #guardian pattern
    if len(words) == 0 or words[0] != 'From': continue
    d[words[2]] = d.get(words[2],0) + 1

print (d)
L'output è:
{'Sat': 1, 'Fri': 20, 'Thu': 6}
 
Ultima modifica:

Giargianas

Nuovo Utente
16
1
Ciao 1nd33d.

Innanzitutto grazie mille per la tua risposta.
Sì, usavo il read perché con readlines lo split() non mi funzionava, dato che comunque devo togliere tutti gli spazi in modo da considerare le parole, e non le lettere, come variabili.
In realtà ieri ci avevo anche provato sia con readline che con readlines, ma senza successo. Ma ero ormai completamente fuso e non mi veniva più nulla. :asd:

Detto ciò provo subito con la tua soluzione e ti aggiorno.
Grazie mille di nuovo.

PS: hai detto bene, uso il 2.7, ma è quello previsto dal corso.
Non appena imparo a padroneggiarlo bene passo al 3 come da tuo suggerimento.
 

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
Sì, usavo il read perché con readlines lo split() non mi funzionava, dato che comunque devo togliere tutti gli spazi in modo da considerare le parole, e non le lettere, come variabili.
Lo split non ti funzionava perchè cercavi di splittare "c" che con readlines() è la lista di righe, ma tu devi splittare la singola linea. Readlines altro non è che uno split sulle righe. Con read() invece non fai molto perchè ti legge l'intero documento con tutte le righe insieme.
Gli spazi non serve toglierli perchè split sugli spazi implicitamente esegue lo strip; il codice che ti ho scritto dovrebbe funzionare anche su python2.7
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!