Программа Python, которая находит наиболее частое слово в TXT файле, должна печатать слово и его количество
Как сейчас, у меня есть функция для замены функции countChars,
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
но когда я запускаю программу, она выплевывает эту мерзость (это всего лишь пример, там около двух страниц слов с огромным количеством отсчетов рядом с ним)
before 1478
battle-field 1478
as 1478
any 1478
altogether 1478
all 1478
ago 1478
advanced. 1478
add 1478
above 1478
Хотя очевидно, что это означает, что код достаточно звучит для запуска, я не получаю от него ничего, чего я хочу.
Он должен печатать, сколько раз каждое слово находится в файле (gb.txt, который является адресом Gettysburg)
Очевидно, что каждое слово, находящееся в файле, не находится ровно в 1478 раз.
Я новичок в программировании, поэтому я немного застенчив.
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()
Ответы
Ответ 1
Если вам нужно подсчитать количество слов в проходе, тогда лучше использовать регулярное выражение.
Начнем с простого примера:
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
Результат:
>>> words
['Wow', 'Is', 'this', 'true', 'Really', 'This', 'is', 'crazy']
Обратите внимание, что "Is" и "is" - это два разных слова. Я предполагаю, что вы хотите, чтобы они считали их одинаковыми, поэтому мы можем просто загладить все слова, а затем посчитать их.
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
Результат:
>>> word_counts
Counter({'THIS': 2, 'IS': 2, 'CRAZY': 1, 'WOW': 1, 'TRUE': 1, 'REALLY': 1})
Вы здесь хорошо?
Теперь нам нужно сделать то же самое, что мы сделали выше, только на этот раз мы читаем файл.
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)
Ответ 2
Эта программа на самом деле является 4-х линейной, если вы используете мощные инструменты в вашем распоряжении:
with open(yourfile) as f:
text = f.read()
words = re.compile(r"[\w']+", re.U).findall(text) # re.U == re.UNICODE
counts = collections.Counter(words)
Регулярное выражение найдет все слова, независимо от примыкающей к ним пунктуации (но считая апострофы как часть слова).
Счетчик действует почти как словарь, но вы можете делать такие вещи, как counts.most_common(10)
, добавлять счетчики и т.д. См. counts.most_common(10)
help(Counter)
Я бы также предложил, чтобы вы не делали функции printBy...
, так как только функции без побочных эффектов легко использовать повторно.
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) )
Демо-версия:
>>> words = Counter(['test','is','a','test'])
>>> printByLine( countsSortedAlphabetically(words, reverse=True) )
test 2
is 1
a 1
отредактировать по адресу Mateusz Konieczny комментарий: заменил [a-zA-Z '] на [\ w']... класс символов \w, в соответствии с документацией по питону, "соответствует символам в слове Unicode; это включает в себя большинство символов, которые могут быть часть слова на любом языке, а также цифры и знак подчеркивания. Если используется флаг ASCII, сопоставляется только [a-zA-Z0-9_]. " (... но явно не соответствует апострофу...) Однако \w включает _ и 0-9, поэтому, если вы не хотите их использовать и не работаете с юникодом, вы можете использовать [a-zA -Z ']; если вы работаете с юникодом, вам нужно сделать отрицательное утверждение или что-то еще, чтобы вычесть [0-9_] из класса символов \w
Ответ 3
У вас есть простая опечатка, words
, где вы хотите word
.
Изменить: Вы, кажется, отредактировали источник. Используйте копию и вставку, чтобы получить ее в первый раз.
Изменить 2: Очевидно, вы не единственный, кто подвержен опечаткам. Реальная проблема в том, что у вас lines
, где вы хотите line
. Приносим извинения за то, что вы обвинили вас в редактировании источника.
Ответ 4
Здесь возможное решение, не столь изящное, как ninjagecko, но все же:
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
Ответ 5
words = ['red', 'green', 'black', 'pink', 'black', 'white', 'black',
'eyes','white', 'black', 'orange', 'pink', 'pink', 'red', 'red',
'white', 'orange', 'white', "black", 'pink', 'green', 'green', 'pink',
'green', 'pink','white', 'orange', "orange", 'red']
from collections import Counter
counts = Counter(words)
top_four = counts.most_common(4)
print(top_four)