使用python检索文档中2个或更多字母的单词总数

问题描述 投票:0回答:4

我有一个小的Python脚本,可以计算.txt文档中前10个最常用的单词,10个最不常用的单词以及单词总数。根据分配,将单词定义为2个字母或更多。我可以打印10个最常用的单词和10个最不常用的单词,但是当我尝试打印文档中的单词总数时,它会打印所有单词的总数,包括单个字母单词(例如“ a” )。如何获取单词总数以仅计算两个或两个以上字母的单词?

这是我的剧本:

from string import *
from collections import defaultdict
from operator import itemgetter
import re

number = 10
words = {}
total_words = 0
words_only = re.compile(r'^[a-z]{2,}$')
counter = defaultdict(int)

"""Define function to count the total number of words"""
def count_words(s):
    unique_words = split(s)
    return len(unique_words)

"""Define words as 2 letters or more -- no single letter words such as "a" """
for word in words:
    if len(word) >= 2:
        counter[word] += 1


"""Open text document, strip it, then filter it"""
txt_file = open('charactermask.txt', 'r')

for line in txt_file:
    total_words = total_words + count_words(line)
    for word in line.strip().split():
        word = word.strip(punctuation).lower()
        if words_only.match(word):
            counter[word] += 1


# Most Frequent Words
top_words = sorted(counter.iteritems(),
                    key=lambda(word, count): (-count, word))[:number] 

print "Most Frequent Words: "

for word, frequency in top_words:
    print "%s: %d" % (word, frequency)


# Least Frequent Words:
least_words = sorted(counter.iteritems(),
                    key=lambda (word, count): (count, word))[:number]

print " "
print "Least Frequent Words: "

for word, frequency in least_words:
    print "%s: %d" % (word, frequency)


# Total Unique Words:
print " "
print "Total Number of Words: %s" % total_words

我不是Python的专家,这是我当前正在学习的Python类。我的代码整洁,格式正确,这对我来说很重要,如果可能的话,有人还可以告诉我这段代码的格式是否被认为是“好的做法”?

python algorithm iteration defaultdict
4个回答
3
投票

列表理解方法:

def countWords(s):
    words = s.split()
    return len([word for word in words if len(word)>=2])

详细方法:

def countWords(s):
    words = s.split()
    count = 0
    for word in words:
        if len(word) >= 2:
            count += 1
    return count

顺便说一句,对使用defaultdict表示赞赏,但我会选择collections.Counter

collections.Counter

希望这会有所帮助


1
投票

算字仅使用split()

您也应该在这里使用match_words正则表达式

words = collections.Counter([word for line in open(filepath) for word in line.strip()])
words = dict((k,v) for k,v in words.iteritems if len(k)>=2)
mostFrequent = [w[0] for w in words.most_common(10)]
leastFrequent = [w[0] for w in words.most_common()[-10:]]

您的样式看起来很棒:)


1
投票

很抱歉,但是我似乎对此解决方案有些不满。我的意思是我已经[分开挑选了您的代码,然后按照我的方式将其放回去:def count_words(s): unique_words = split(s) return len(filter(lambda x: words_only.match(x):, unique_words))

以下是我所做更改的摘要,以及原因

  • Do n't do from collections import defaultdict from operator import itemgetter from heapq import nlargest, nsmallest from itertools import starmap from textwrap import dedent import re class WordCounter(object): """ Count the number of words consisting of two letters or more. """ words_only = re.compile(r'[a-z]{2,}', re.IGNORECASE) def __init__(self, filename, number=10): self.counter = defaultdict(int) # Open text document and find all words with open(filename, 'r') as txt_file: for word in self.words_only.findall(txt_file.read()): self.counter[word.lower()] += 1 # Get total count self.total_words = sum(self.counter.values()) # Most Frequent Words self.top_words = nlargest( number, self.counter.items(), itemgetter(1)) # Least Frequent Words self.least_words = nsmallest( number, self.counter.items(), itemgetter(1)) def __str__(self): """ Summary of least and most used words, and total word count. """ template = dedent(""" Most Frequent Words: {0} Least Frequent Words: {1} Total Number of Words: {2} """) line_template = "{0}: {1}".format top_words = "\n".join(starmap(line_template, self.top_words)) least_words = "\n".join(starmap(line_template, self.least_words)) return template.format(top_words, least_words, self.total_words) print WordCounter("charactermask.txt")

    某些模块旨在让您安全地执行此操作,但是由于名称空间污染,通常这是一个坏主意。仅导入您需要的东西,或导入缩写的模块:from x import *。这将减少错误代码。
  • [使其成为一个类。

  • 尽管将它们作为脚本编写对于这些事情而言是不错的选择,但是始终将代码包装在类或函数中以更好地组织代码以及在您使用代码时是一个好习惯在另一个项目中需要它们。然后,您只需执行import string as st,就可以了。
  • [from wordcounter import WordCounter在代码块内移动。

  • 这样,如果您在交互式解释器中键入Docstrings,它们将被自动使用。
  • 注释通常以help(my_class_or_function)为前缀,而不是一次性字符串

  • 。这不是一个很大的禁忌,而是一个相当普遍的约定。
  • 打开文件时使用#

  • 。这是个好习惯。您不必担心要记住将其关闭。
  • [with statement是多余的。

  • 仅使用with
  • 使用.strip().split()

  • 避免了诸如“ top-notch”之类的单词的问题,使用您的方法根本不会计算这些单词。根据定义,使用.split()来计算“顶部”和“缺口”。而且,它更快。但是我们必须稍微修改一下正则表达式。
  • re.findall dict未使用。

  • 已删除。
  • 使用re.findall计算总单词数。

  • 这解决了您和inspectorG4dgets代码中的问题,其中每个单词实际上需要使用findall模式两次-总计一次然后一次进行字数统计-以获得一致的结果。
  • 使用words

  • 当您只需要n个最小或最大的结果时,它们比完整排序要快且内存效率更高。
  • 使函数返回您可能希望打印或不希望打印的字符串。

  • 直接使用print语句的灵活性较差,尽管非常适合调试。
  • 对于新代码,请使用sum字符串方法而不是words_only运算符。

  • 前者经过改进,可以代替后者。
  • 使用多行字符串而不是多个连续的打印。

  • 更容易看到实际写入的内容,并且更易于维护。如果要将字符串缩进到与周围代码相同的级别,则heapq.nlargest and heapq.nsmallest功能会有所帮助。
    [还有一个更易读的问题:heapq.nlargestheapq.nsmallest。大多数人总是喜欢列表理解,并且我通常也同意它们,但是在这里,我喜欢starmap方法的简洁性。

话虽如此,我同意user1552512,您的风格看起来很棒!精美,易读的代码,注释良好,非常符合format。你会走的很远。 :)


0
投票
个人,我认为您的代码看起来不错。我不知道它的“标准” python样式是否容易理解。我对Python也很陌生,但这是我的答案。

0
投票
我通过将代码分类为最常用的单词,在代码末尾收到回溯(无效的语法)>

%

该代码不喜欢我在代码中标记的括号。

有人知道解决方案吗?

我正在使用python最新的python 3版本。

© www.soinside.com 2019 - 2024. All rights reserved.