Este team de expertos despúes de algunos días de investigación y de recopilar de información, obtuvimos la respuesta, deseamos que te sea de gran utilidad para tu trabajo.
Solución:
Si no desea utilizar colecciones.Counter, puede escribir su propia función:
import sys
filename = sys.argv[1]
fp = open(filename)
data = fp.read()
words = data.split()
fp.close()
unwanted_chars = ".,-_ (and so on)"
wordfreq =
for raw_word in words:
word = raw_word.strip(unwanted_chars)
if word not in wordfreq:
wordfreq[word] = 0
wordfreq[word] += 1
para cosas más finas, observe las expresiones regulares.
Aunque usando Counter
desde el collections
library como lo sugiere @Michael es un mejor enfoque, estoy agregando esta respuesta solo para mejorar su código. (Creo que esta será una buena respuesta para un nuevo alumno de Python).
Del comentario en tu código parece que quieres mejorar tu código. Y creo que puedes leer el contenido del archivo en palabras (aunque normalmente evito usar read()
función y uso for line in file_descriptor:
tipo de código).
Como words
es un string, en bucle for, for i in words:
la variable de bucle i
es no una palabra sino un char. Estás iterando sobre caracteres en el string en lugar de iterar sobre las palabras en el string words
. Para comprender esto, observe el siguiente fragmento de código:
>>> for i in "Hi, h r u?":
... print i
...
H
i
,
h
r
u
?
>>>
Porque iterando sobre lo dado string char por caracteres en lugar de palabra por palabras no es lo que quería lograr, para iterar palabras por palabras debe usar el split
método / función de string clase en Python.str.split(str="", num=string.count(str))
método devoluciones una lista de todas las palabras en el string, utilizando str como separador (se divide en todos los espacios en blanco si no se especifica), limitando opcionalmente el número de divisiones a num.
Observe los ejemplos de código a continuación:
Separar:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?']
bucle con división:
>>> for i in "Hi, how are you?".split():
... print i
...
Hi,
how
are
you?
Y parece algo que necesitas. Excepto por la palabra Hi,
porque split()
, de forma predeterminada, se divide por espacios en blanco para Hi,
se mantiene como un solo string (y obviamente) no quieres eso.
Para contar la frecuencia de palabras en el archivo, una buena solución es usar expresiones regulares. Pero primero, para mantener la respuesta simple, usaré replace()
método. El método str.replace(old, new[, max])
devuelve una copia del string en el que las ocurrencias antiguas se han reemplazado por nuevas, restringiendo opcionalmente el número de reemplazos al máximo.
Ahora verifique el ejemplo de código a continuación para ver lo que sugerí:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?'] # it has , with Hi
>>> "Hi, how are you?".replace(',', ' ').split()
['Hi', 'how', 'are', 'you?'] # , replaced by space then split
círculo:
>>> for word in "Hi, how are you?".replace(',', ' ').split():
... print word
...
Hi
how
are
you?
Ahora, cómo contar la frecuencia:
Una forma es el uso Counter
como sugirió @Michael, pero para usar su enfoque en el que desea comenzar desde un dict vacío. Haga algo como este ejemplo de código a continuación:
words = f.read()
wordfreq =
for word in .replace(', ',' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
# ^^ add 1 to 0 or old value from dict
¿Qué estoy haciendo? Porque inicialmente wordfreq
está vacío, no puedes asignarlo wordfreq[word]
por primera vez (se levantará key error de excepción). Entonces usé setdefault
método dict.
dict.setdefault(key, default=None)
es parecido a get()
, pero establecerá dict[key]=default
si key no está ya en dict. Entonces, por primera vez, cuando aparece una nueva palabra, la configuro con 0
en dict usando setdefault
Luego añade 1
y asignar al mismo dict.
He escrito un código equivalente usando open en lugar de single open
.
with open('~/Desktop/file') as f:
words = f.read()
wordfreq =
for word in words.replace(',', ' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
Eso funciona así:
$ cat file # file is
this is the textfile, and it is used to take words and count
$ python work.py # indented manually
'and': 2, 'count': 1, 'used': 1, 'this': 1, 'is': 2,
'it': 1, 'to': 1, 'take': 1, 'words': 1,
'the': 1, 'textfile': 1
Utilizando re.split(pattern, string, maxsplit=0, flags=0)
Simplemente cambie el bucle for: for i in re.split(r"[,s]+", words):
, eso debería producir la salida correcta.
Editar: es mejor encontrar todos los caracteres alfanuméricos porque puede tener más de un símbolo de puntuación.
>>> re.findall(r'[w]+', words) # manually indent output
['this', 'is', 'the', 'textfile', 'and',
'it', 'is', 'used', 'to', 'take', 'words', 'and', 'count']
utilizar for loop como: for word in re.findall(r'[w]+', words):
¿Cómo escribiría código sin usar read()
:
El archivo es:
$ cat file
This is the text file, and it is used to take words and count. And multiple
Lines can be present in this file.
It is also possible that Same words repeated in with capital letters.
El código es:
$ cat work.py
import re
wordfreq =
with open('file') as f:
for line in f:
for word in re.findall(r'[w]+', line.lower()):
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
Usó lower()
para convertir una letra mayúscula en una letra minúscula.
producción:
$python work.py # manually strip output
'and': 3, 'letters': 1, 'text': 1, 'is': 3,
'it': 2, 'file': 2, 'in': 2, 'also': 1, 'same': 1,
'to': 1, 'take': 1, 'capital': 1, 'be': 1, 'used': 1,
'multiple': 1, 'that': 1, 'possible': 1, 'repeated': 1,
'words': 2, 'with': 1, 'present': 1, 'count': 1, 'this': 2,
'lines': 1, 'can': 1, 'the': 1
from collections import Counter
t = 'this is the textfile, and it is used to take words and count'
dict(Counter(t.split()))
>>> 'and': 2, 'is': 2, 'count': 1, 'used': 1, 'this': 1, 'it': 1, 'to': 1, 'take': 1, 'words': 1, 'the': 1, 'textfile,': 1
O mejor eliminando la puntuación antes de contar:
dict(Counter(t.replace(',', '').replace('.', '').split()))
>>> 'and': 2, 'is': 2, 'count': 1, 'used': 1, 'this': 1, 'it': 1, 'to': 1, 'take': 1, 'words': 1, 'the': 1, 'textfile': 1
Recuerda algo, que te brindamos la opción de añadir un criterio justo .