Estoy tratando de contar todas las letras en un archivo txt y luego mostrarlas en orden descendente

Como dice el título:

Hasta ahora, aquí es donde funciona mi código, pero tengo problemas para mostrar la información en orden. Actualmente solo muestra la información al azar.

def frequencies(filename): infile=open(filename, 'r') wordcount={} content = infile.read() infile.close() counter = {} invalid = "''`,.?!:;-_\n—' '" for word in content: word = content.lower() for letter in word: if letter not in invalid: if letter not in counter: counter[letter] = content.count(letter) print('{:8} appears {} times.'.format(letter, counter[letter])) 

Cualquier ayuda sería muy apreciada.

La visualización en orden descendente debe estar fuera de su ciclo de búsqueda, de lo contrario se mostrarán a medida que se encuentren.

La clasificación en orden descendente es bastante fácil utilizando la ordenación incorporada (¡tendrá que configurar el reverse -argumento!)

Sin embargo, Python incluye baterías y ya hay un Counter . Entonces podría ser tan simple como:

 from collections import Counter from operator import itemgetter def frequencies(filename): # Sets are especially optimized for fast lookups so this will be # a perfect fit for the invalid characters. invalid = set("''`,.?!:;-_\n—' '") # Using open in a with block makes sure the file is closed afterwards. with open(filename, 'r') as infile: # The "char for char ...." is a conditional generator expression # that feeds all characters to the counter that are not invalid. counter = Counter(char for char in infile.read().lower() if char not in invalid) # If you want to display the values: for char, charcount in sorted(counter.items(), key=itemgetter(1), reverse=True): print(char, charcount) 

El contador ya tiene un método most_common pero desea mostrar todos los caracteres y los conteos, por lo que no es un buen ajuste en este caso. Sin embargo, si solo desea conocer los x recuentos más comunes, entonces sería adecuado.

Los diccionarios son estructuras de datos desordenados. Además, si desea contar algunos elementos dentro de un conjunto de datos, es mejor utilizar collections.Counter() que está más optimizado y es más python para este objective.

Luego, solo puede usar Counter.most_common(N) para imprimir la mayoría de los N elementos comunes dentro de su objeto Counter.

También con respecto a la apertura de archivos, simplemente puede usar la instrucción with que cierra el archivo al final del bloque automáticamente. Y es mejor no imprimir el resultado final dentro de su función, ya que puede convertir su función en un generador generando las líneas deseadas e imprimiéndolas cuando lo desee.

 from collections import Counter def frequencies(filename, top_n): with open(filename) as infile: content = infile.read() invalid = "''`,.?!:;-_\n—' '" counter = Counter(filter(lambda x: not invalid.__contains__(x), content)) for letter, count in counter.most_common(top_n): yield '{:8} appears {} times.'.format(letter, count) 

Luego use un bucle for para iterar sobre la función del generador:

 for line in frequencies(filename, 100): print(line) 

No necesita iterar sobre ‘palabras’, y luego sobre letras en ellas. Cuando recorres una cadena (como el content ), ya tendrás caracteres individuales (longitud 1 cadenas). Luego, desearía esperar hasta que finalice su ciclo de conteo antes de mostrar la salida. Después de contar, puedes ordenar manualmente:

 for letter, count in sorted(counter.items(), key=lambda x: x[1], reverse=True): # do stuff 

Sin embargo, mejor uso de las collections.Counter . collections.Counter :

 from collections import Counter content = filter(lambda x: x not in invalid, content) c = Counter(content) for letter, count in c.most_common(): # descending order of counts print('{:8} appears {} times.'.format(letter, number)) # for letter, number in c.most_common(n): # limit to n most # print('{:8} appears {} times.'.format(letter, count)) 

Puede ordenar su diccionario en el momento de imprimir, con el método sorted :

 lettercount = {} invalid = "''`,.?!:;-_\n—' '" infile = open('text.file') for c in infile.read().lower(): if c not in invalid: lettercount[c] = lettercount.setdefault(c,0) + 1 for letter in sorted(lettercount): print("{} appears {} times".format(letter,lettercount[letter])) 

Rmq: setdefault método de cambio setdefault para establecer el valor predeterminado en 0 cuando nos encontramos con una letra por primera vez