gpt4 book ai didi

python - 执行计数、排序/映射大型字典

转载 作者:太空宇宙 更新时间:2023-11-04 03:39:16 26 4
gpt4 key购买 nike

我正在做这周的“简单”Daily Programmer Challenge在 Reddit 上。描述在链接中,但本质上挑战是从 url 读取文本文件并进行字数统计。不用说,结果输出是一个相当大的字典对象。我有几个问题,主要是关于根据键的值访问或排序键。

首先,我根据我目前对 OOP 的了解和良好的 Python 风格开发了代码。我希望它尽可能健壮,但我也想使用最少数量的导入模块。我的目标是成为一名优秀的程序员,因此我认为打好坚实的基础并尽可能自己弄清楚如何做事很重要。话虽如此,代码:

from urllib2 import urlopen

class Word(object):

def __init__(self):
self.word_count = {}

def alpha_only(self, word):
"""Converts word to lowercase and removes any non-alphabetic characters."""
x = ''
for letter in word:
s = letter.lower()
if s in 'abcdefghijklmnopqrstuvwxyz':
x += s
if len(x) > 0:
return x

def count(self, line):
"""Takes a line from the file and builds a list of lowercased words containing only alphabetic chars.
Adds each word to word_count if not already present, if present increases the count by 1."""
words = [self.alpha_only(x) for x in line.split(' ') if self.alpha_only(x) != None]
for word in words:
if word in self.word_count:
self.word_count[word] += 1
elif word != None:
self.word_count[word] = 1

class File(object):

def __init__(self,book):
self.book = urlopen(book)
self.word = Word()

def strip_line(self,line):
"""Strips newlines, tabs, and return characters from beginning and end of line. If remaining string > 1,
splits up the line and passes it along to the count method of the word object."""
s = line.strip('\n\r\t')
if s > 1:
self.word.count(s)

def process_book(self):
"""Main processing loop, will not begin processing until the first line after the line containing "START".
After processing it will close the file."""
begin = False
for line in self.book:
if begin == True:
self.strip_line(line)
elif 'START' in line:
begin = True
self.book.close()

book = File('http://www.gutenberg.org/cache/epub/47498/pg47498.txt')

book.process_book()

count = book.word.word_count

所以现在我有一个相当准确和强大的字数统计,可能没有任何重复项或空白条目,但仍然是一个包含超过 3k 键/值对的字典对象。我无法使用 for k,v in count 对其进行迭代,否则会出现异常 ValueError: too many values to unpack,这排除了使用列表理解或映射的可能性到一个函数来执行任何类型的排序。

我正在读这个HowTo on Sorting几分钟前玩了一下,注意到 for x in count.items() 让我遍历键/值对列表而不抛出 ValueError 异常,所以我删除了行 count = book.word.word_count 并添加以下内容:

s_count = sorted(book.word.word_count.items(), key=lambda count: count[1], reverse=True)

# Delete the original dict, it is no longer needed
del book.word.word_count

现在我终于有了一个排序的单词列表,s_count。呸!所以,我的问题是:

  1. 字典是执行原始计数的最佳数据类型吗?像 count.items() 返回的那样的元组列表会更好吗?但这可能会减慢速度,对吧?

  2. 这看起来有点“笨拙”,因为我正在构建一个字典,将其转换为包含元组的列表,然后对列表进行排序并返回一个新列表。但是,据我了解,字典可以让我执行最快的查找,所以我是否遗漏了什么?

  3. 我简要阅读了有关哈希的内容。虽然我认为我理解关键是散列将节省内存空间并允许我执行更快的查找和比较,但权衡是否会导致程序变得更昂贵(更高的 CPU 负载),因为它会然后计算每个单词的哈希值?这里哈希相关吗?

  4. 任何关于命名约定(我很糟糕)的反馈,或任何关于基本上任何东西(包括风格)的任何其他建议,将不胜感激。

最佳答案

您确定 for k,v in count: 给出异常 ValueError: too many values to unpack?我希望它给出 ValueError: need more than 1 value to unpack

当您将dict 用作迭代器时(例如在for 循环中),您只会得到键,而不会得到值。如果你想要键值对,你需要使用 dictiteritems() 方法,正如 figs 在评论中提到的(或者在 Python 3 中的 items () 方法)。

当然,您可以随时执行以下操作:

for k in count:
print k, count[k]

...

我认为你的大部分问题更适合Code Review比堆栈溢出。但既然你在这里问得很好,我会提几点。 :)

逐个字符地构建字符串效率相当低,因此如果您的 alpha_only() 方法在列表中收集字符然后使用 str.join() 方法将它们连接成一个字符串。通常的 Python 惯用语会使用列表理解来做到这一点。

count() 方法中的列表理解为每个单词调用两次 alpha_only(),效率很高。

您可以使用默认参数使您的 strip() 调用更简单,因为它会去除所有空白(并且您不需要在此应用程序中保留空格字符)。类似地,使用 split() 及其默认 arg 将在任何空格运行时拆分,这在这个应用程序中可能更好,因为给一个 arg 一个空格意味着你会得到一些空的如果一行中有任何多个空格的运行,则 split 返回的列表中的字符串。

...

您在问题中提到了散列,以及它是否对这个应用程序有用。是的。 Python 字典实际上使用它们的键的散列,因此您无需担心细节。是的,字典是用于此任务的良好数据结构。有更高级的字典形式可以使事情变得更简单,但要使用它们确实需要导入一个(标准)模块。但是使用字典(某种风格或其他风格)来保存数据,然后从中生成元组列表以进行最终排序是 Python 中相当常见的做法。如果程序即将终止,则在完成字典后无需专门删除字典。

...

至于 alpha_only() 的重复调用,每当您发现自己在做那种事情时,这表明列表理解并不真正适合该任务,您应该只使用一个普通的 for 循环,这样您就可以保存函数调用的结果,而不必重新计算它。例如,

words = []
for word in line.split():
word = self.alpha_only(word)
if word is not None:
words.append(word)

关于python - 执行计数、排序/映射大型字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27339871/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com