2012-04-30 8 views
9

A partir de ahora, tengo una función para reemplazar la función countChars,programa en Python que encuentra la palabra más frecuente en un archivo .txt, debe imprimir palabra y su recuento

def countWords(lines): 
    wordDict = {} 
    for line in lines: 
    wordList = lines.split() 
    for word in wordList: 
     if word in wordDict: wordDict[word] += 1 
     else: wordDict[word] = 1 
    return wordDict 

pero cuando ejecuto el programa escupe esta abominación (esto es sólo un ejemplo, hay cerca de dos páginas de palabras con un enorme número de serie junto a él)

before 1478 
battle-field 1478 
as 1478 
any 1478 
altogether 1478 
all 1478 
ago 1478 
advanced. 1478 
add 1478 
above 1478 

Aunque obviamente esto significa que el código es lo suficientemente sólidas como para funcionar, estoy no obtengo lo que quiero de eso. que necesita para imprimir el número de veces que cada palabra está en el archivo (gb.txt, que es la dirección de Gettysburg) Obviamente cada palabra que se encuentra en el archivo no está ahí exactamente 1478 veces ..

I' m bastante nuevo en la programación, por lo que estoy un poco perplejo ..

from __future__ import division 

inputFileName = 'gb.txt' 

def readfile(fname): 
    f = open(fname, 'r') 
    s = f.read() 
    f.close() 
return s.lower() 

def countChars(t): 
    charDict = {} 
    for char in t: 
    if char in charDict: charDict[char] += 1 
    else: charDict[char] = 1 
    return charDict 

def findMostCommon(charDict): 
    mostFreq = '' 
    mostFreqCount = 0 
    for k in charDict: 
    if charDict[k] > mostFreqCount: 
     mostFreqCount = charDict[k] 
     mostFreq = k 
    return mostFreq 

def printCounts(charDict): 
    for k in charDict: 
    #First, handle some chars that don't show up very well when they print 
    if k == '\n': print '\\n', charDict[k] #newline 
    elif k == ' ': print 'space', charDict[k] 
    elif k == '\t': print '\\t', charDict[k] #tab 
    else: print k, charDict[k] #Normal character - print it with its count 

def printAlphabetically(charDict): 
    keyList = charDict.keys() 
    keyList.sort() 
    for k in keyList: 
    #First, handle some chars that don't show up very well when they print 
    if k == '\n': print '\\n', charDict[k] #newline 
    elif k == ' ': print 'space', charDict[k] 
    elif k == '\t': print '\\t', charDict[k] #tab 
    else: print k, charDict[k] #Normal character - print it with its count 

def printByFreq(charDict): 
    aList = [] 
    for k in charDict: 
    aList.append([charDict[k], k]) 
    aList.sort()  #Sort into ascending order 
    aList.reverse() #Put in descending order 
    for item in aList: 
    #First, handle some chars that don't show up very well when they print 
    if item[1] == '\n': print '\\n', item[0] #newline 
    elif item[1] == ' ': print 'space', item[0] 
    elif item[1] == '\t': print '\\t', item[0] #tab 
    else: print item[1], item[0] #Normal character - print it with its count 

def main(): 
    text = readfile(inputFileName) 
    charCounts = countChars(text) 
    mostCommon = findMostCommon(charCounts) 
    #print mostCommon + ':', charCounts[mostCommon] 
    #printCounts(charCounts) 
    #printAlphabetically(charCounts) 
    printByFreq(charCounts) 

main() 

Respuesta

14

Si necesita contar con un número de palabras en un pasaje, entonces es mejor usar expresiones regulares. inicio

Vamos con un ejemplo sencillo:

import re 

my_string = "Wow! Is this true? Really!?!? This is crazy!" 

words = re.findall(r'\w+', my_string) #This finds words in the document 

Resultado:

>>> words 
['Wow', 'Is', 'this', 'true', 'Really', 'This', 'is', 'crazy'] 

Tenga en cuenta que "es" y "es" son dos palabras diferentes. Supongo que quieres que los cuente igual, así que solo podemos capitalizar todas las palabras y luego contarlas.

from collections import Counter 

cap_words = [word.upper() for word in words] #capitalizes all the words 

word_counts = Counter(cap_words) #counts the number each time a word appears 

Resultado:

>>> word_counts 
Counter({'THIS': 2, 'IS': 2, 'CRAZY': 1, 'WOW': 1, 'TRUE': 1, 'REALLY': 1}) 

¿Eres bueno hasta aquí?

Ahora tenemos que hacer exactamente lo mismo que hicimos anteriormente, solo que esta vez estamos leyendo un archivo.

import re 
from collections import Counter 

with open('your_file.txt') as f: 
    passage = f.read() 

words = re.findall(r'\w+', passage) 

cap_words = [word.upper() for word in words] 

word_counts = Counter(cap_words) 
+0

Wow. Si bien este puede no ser el método que nuestro profesor quiere que usemos, esto funciona perfectamente para encontrar el conteo de números. En este punto, preferiría obtenerlos para que se impriman en una sola columna para poder leerlos. También hay varias partes en la tarea, que incluyen: Solo imprime la palabra más común. Imprimiendo todas las palabras con sus recuentos en orden alfabético. Y luego imprima todas las palabras con sus recuentos en orden de frecuencia. Estos son bastante simples, si no me equivoco, pero no sé si lo que he aprendido es compatible con lo que me has dado hasta ahora. – m96

+0

Las tareas que mencionas no son muy difíciles, necesitarías usar '.sort()' o 'sorted()', quizás buscar cómo ordenar un diccionario. Es su tarea, y debe hacerlo;), pero si está atrapado en alguna parte, publique lo que tiene (como otra pregunta) y alguien lo ayudará. – Akavall

17

Este programa es en realidad un 4-liner, si utiliza las poderosas herramientas a su disposición:

with open(yourfile) as f: 
    text = f.read() 

words = re.compile(r"a-zA-Z'").findall(text) 
counts = collections.Counter(words) 

La regulares expresión encontrará todas las palabras, independientemente de la puntuación adjac a ellos (pero contando apóstrofes como parte de la palabra).

Un contador actúa casi como un diccionario, pero se puede hacer cosas como counts.most_common(10), y añadir los recuentos, etc. Ver help(Counter)

También sugeriría que no hacen funciones printBy..., ya que sólo las funciones sin la lado- los efectos son fáciles de reutilizar.

def countsSortedAlphabetically(counter, **kw): 
    return sorted(counter.items(), **kw) 

#def countsSortedNumerically(counter, **kw): 
# return sorted(counter.items(), key=lambda x:x[1], **kw) 
#### use counter.most_common(n) instead 

# `from pprint import pprint as pp` is also useful 
def printByLine(tuples): 
    print('\n'.join(' '.join(map(str,t)) for t in tuples)) 

Demostración:

>>> words = Counter(['test','is','a','test']) 
>>> printByLine(countsSortedAlphabetically(words, reverse=True)) 
test 2 
is 1 
a 1 
+0

Yikes, pensé que había mencionado que esto era en Python 2.7. – m96

+3

@ZachCorse Lo mismo ocurre con ['collections.Counter'] (http://docs.python.org/library/collections.html#collections.Counter) –

+0

@ninjagecko Claramente, sabes lo que estás haciendo, pero esto parece ser por delante de lo que he aprendido actualmente. Probablemente parezca una tontería, pero cuando pruebo cualquiera de estas cosas, más específicamente la primera que publicaste, recibo un error de nombre como este. 'words = re.compile (r" a-zA-Z '"). Findall (texto) NameError: name' re 'no está definido' – m96

3

Usted tiene un simple error tipográfico, words donde desea word.

Editar: Parece que ha editado la fuente. Utilice copiar y pegar para hacerlo bien la primera vez.

Editar 2: Parece que no eres el único propenso a los errores tipográficos. El verdadero problema es que tiene lines donde desea line. Me disculpo por haberle acusado de editar la fuente.

+0

No está seguro de lo que quiere decir. Reemplacé la función que busca caracteres por la que busca palabras y reemplacé una palabra en la función principal para que se ejecutara. – m96

+0

@ZachCorse, me equivoqué - ver mi última edición. –

+0

Cuando elimino el s de las líneas solo cuenta los caracteres. EDITAR: Oops, presiona entrar demasiado rápido. Lo necesito para contar cuántos de cada palabra hay dentro del archivo. Con las minúsculas adjuntas a las líneas, observa cuántas palabras hay, pero no las cuenta. (hay números, pero en general son todos iguales por alguna razón) – m96

1

Aquí una posible solución, no tan elegante como de ninjagecko pero aún así:

from collections import defaultdict 

dicto = defaultdict(int) 

with open('yourfile.txt') as f: 
    for line in f: 
     s_line = line.rstrip().split(',') #assuming ',' is the delimiter 
     for ele in s_line: 
      dicto[ele] += 1 

#dicto contians words as keys, word counts as values 

for k,v in dicto.iteritems(): 
    print k,v 
+0

Quizás deba publicar una muestra de su archivo, para que podamos ver cómo se ve el formato. – Akavall

+0

@ZachCorse: puede encontrar http://www.ibm.com/developerworks/web/library/wa-debug/index.html para ser perspicaz al aprender a programar. – ninjagecko

Cuestiones relacionadas