- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在做这周的“简单”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
。呸!所以,我的问题是:
字典是执行原始计数的最佳数据类型吗?像 count.items()
返回的那样的元组列表会更好吗?但这可能会减慢速度,对吧?
这看起来有点“笨拙”,因为我正在构建一个字典,将其转换为包含元组的列表,然后对列表进行排序并返回一个新列表。但是,据我了解,字典可以让我执行最快的查找,所以我是否遗漏了什么?
我简要阅读了有关哈希的内容。虽然我认为我理解关键是散列将节省内存空间并允许我执行更快的查找和比较,但权衡是否会导致程序变得更昂贵(更高的 CPU 负载),因为它会然后计算每个单词的哈希值?这里哈希相关吗?
任何关于命名约定(我很糟糕)的反馈,或任何关于基本上任何东西(包括风格)的任何其他建议,将不胜感激。
最佳答案
您确定 for k,v in count:
给出异常 ValueError: too many values to unpack
?我希望它给出 ValueError: need more than 1 value to unpack
。
当您将dict
用作迭代器时(例如在for
循环中),您只会得到键,而不会得到值。如果你想要键值对,你需要使用 dict
的 iteritems()
方法,正如 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/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improve
我有点卡在 JavaScript 逻辑上来完成这个任务。 基本上 如果我给出一个数字(比如 30) 我想在两边都显示 5。 所以 25 26 27 28 29 30 31 32 33 34 35 这部
我编写的程序有问题。我无法获得输入字符串的正确字数,但我获得了正确的最长字符数。我不知道为什么,但这是我的代码。我正在做的是将一个字符串传递给一个函数,该函数将字符串中的所有字母大写。然后,该函数逐个
我有功能 public ArrayList vyberNahodnaPismena() { String[] seznamPismen = {"A", "Á", "B", "C", "Č",
这可以在 PGSQL 中完成吗?我有一个我创建的 View ,其中主机名、ip 和数据中心来自一个表,ifdesc 和 if stats 来自另一个表。 View 输出如下所示: hostname |
我想要一组来自订单文件的数据,这些数据可以为我提供客户编号、订单编号、产品、数量、价格以及每个订单的订单详细信息文件中的行数。我在最后一部分遇到问题。 Select Header.CustNo, He
我有属于街道的房子。一个用户可以买几套房子。我如何知道用户是否拥有整条街道? street table with columns (id/name) house table with columns
我有一套有 200 万个主题标签。然而,只有大约 200k 是不同的值。我想知道哪些主题标签在我的数据中重复得更多。 我用它来查找每个主题标签在我的数据集上重复了多少次: db.hashtags.ag
我有如下文件: { "_id" : "someuniqueeventid", "event" : "event_type_1", "date" : ISODate("2014-
我有以下三个相互关联的表: 主持人(有多个 session ) session (有多个进程) 过程 表结构如下: 主机表 - id, name session 表 - id, host_id, na
我需要根据 2 个字段对行进行计数以进行分组。 动物(一) id group_id strain_id death_date death_cause status --
我有一个 LINQ 语句,我正在努力改正,所以可能这一切都错了。我的目标是查询一个表并加入另一个表以获取计数。 地点 标识、显示 ProfilePlaces ID、PlaceID、通话、聆听 基本上P
我无法编写 Countifs 来完成我想要的。我每个月都会运行一份 claim 报告,其中包含大量按列组织的数据,并每月将其导出到 Excel 中。在一个单独的选项卡上,我有引用此数据复制到的选项卡的
我有一些数据采用此 sqlfilddle 中描述的格式:http://sqlfiddle.com/#!4/b9cdf/2 基本上,一个包含用户 ID 和事件发生时间的表。我想做的是根据用户发生事件的时
我有以下 SQL 语句: SELECT [l.LeagueId] AS LeagueId, [l.LeagueName] AS NAME, [lp.PositionId] FROM
我试图找出一个值在列中出现的平均次数,根据另一列对其进行分组,然后对其进行计算。 我有 3 张 table ,有点像这样 DVD ID | NAME 1 | 1 2 | 1 3
我有一个非常简单的 SQL 问题。我有一个包含以下列的数据库表: 零件号 销售类型(为简单起见,称之为销售类型 1、2、3、4、5) 我希望编写一个包含以下三列的查询: 零件号 Sales Type
我创建了以下存储过程,用于计算选定位置的特定范围之间每天的记录数: [dbo].[getRecordsCount] @LOCATION as INT, @BEGIN as datetime, @END
我有一个包含一组列的表,其中一个是日期列。 我需要计算该列的值引用同一个月的次数。如果一个月内,该计数的总和超过 3,则返回。 例如: ____________________ | DATE |
看XXX数据如下: lala XXX = EL String [XXX] | TXT String | MMS String 为此,XXX数据yppz是由 lala
我是一名优秀的程序员,十分优秀!