(我对任何一种编程都是全新的,因此在回答时请尽可能具体)
问题:我编写了一个程序来解决pythonchallenge.com 2级问题。该程序可以运行,但是结果混乱。 我想将字符计数的结果排序到一个漂亮的列表中。 当我尝试使用sorted()对字符计数的结果进行排序时,它会删除所有计数,并仅列出字符串中的字符。 我需要能够查看文件中每个字符的数量。 无论如何,这里是代码:
countstring = open('pagesource.txt').read()
charcount = {}
for x in countstring:
charcount[x] = charcount.get(x, 0) + 1
print charcount
这就是我在cmd中得到的:
>>> {'
': 1219, '!': 6079, '#': 6115, '%': 6104, '$': 6046, '&': 6043, ')': 6186, '
(': 6154, '+': 6066, '*': 6034, '@': 6157, '[': 6108, ']': 6152, '_': 6112, '^':
6030, 'a': 1, 'e': 1, 'i': 1, 'l': 1, 'q': 1, 'u': 1, 't': 1, 'y': 1, '{': 6046
, '}': 6105}
如果我向其中添加诸如print sorted(charcount)之类的sorted()函数,则会在cmd中获得此信息:
>>> ['
', '!', '#', '$', '%', '&', '(', ')', '*', '+', '@', '[', ']', '^', '_', 'a'
, 'e', 'i', 'l', 'q', 't', 'u', 'y', '{', '}']
感谢您的解决方案,如果您能抽出宝贵的时间向代码中添加注释,以解释一切,我将不胜感激!
您应该真正使用Counter类,而不是重新发明自己的轮子。
charcount是一个字典,并且字典没有隐式的排序顺序。因此,我们必须将其转换为可以排序的列表。该列表中的每个条目将是一个由计数和字符组成的元组。
charcount.items()已经给我们一个类似于[('
', 1219), ('!', 6079)]的列表。不幸的是,如果我们对该列表进行排序,它将首先按字符排序,然后(如果字符相等)按计数排序,而不是相反。因此,我们需要一个键函数来告诉排序先查看计数,然后再查看(如果计数相等)字符。幸运的是,我们的关键功能非常简单。它只是在元组周围交换:
lambda (char,count): (count, char)
或者,我们可以使用列表推导来交换值,得到类似:[('
', 1219), ('!', 6079)],然后进行排序,然后再次交换值。
charcount_list = sorted(charcount.items(), key=lambda (char,count):(count, char))
charcount_list现在将是:
[('a', 1), ('e', 1), ('i', 1), ('l', 1), ('q', 1), ('t', 1), ('u', 1), ('y', 1),
('
', 1219), ('^', 6030), ('*', 6034), ('&', 6043), ('$', 6046), ('{', 6046),
('+', 6066), ('!', 6079), ('%', 6104), ('}', 6105), ('[', 6108), ('_', 6112),
('#', 6115), (']', 6152), (' (', 6154), ('@', 6157), (')', 6186)]
如果需要相反的顺序,只需指定要排序的reverse=True参数即可。
在2.7之前的版本中至少为defaultdict。
这是一个丑陋的键函数-使用您最初在此处具有的列表理解,或者如果您真的想同时按值和键进行排序,请使用itemgetter(1, 0)。
@agf为什么那个lambda丑陋?每个Python程序员都会立即了解这里发生的事情。我同意使用itemgetter会使它更短一些(如果您不算导入的话),但不一定更具可读性。
与sorted((v, k) for k, v in charcount.iteritems())或itemgetter版本相比,它对我来说看起来很丑。
>>> from operator import itemgetter
>>> sorted(charcount.items(), key=itemgetter(1))
[('a', 1), ('e', 1), ('i', 1), ('l', 1), ('q', 1), ('u', 1), ('t', 1), ('y', 1), ('
', 1219), ('^', 6030), ('*', 6034), ('&', 6043), ('$', 6046), ('{', 6046), ('+', 6066), ('!', 6079), ('%', 6104), ('}', 6105), ('[', 6108), ('_', 6112), ('#', 6115), (']', 6152), (' (', 6154), ('@', 6157), (')', 6186)]
尽管这很简洁,但问题提出了:"我需要保持查看文件中每个字符的数量的能力"。
@phihag,是的,我看到并修复了它
字典({}的含义)是无序集合。这意味着您无法以任何有意义的方式对它们进行排序。我建议将信息存储为元组[(),...]的列表,然后根据该列表对其进行排序。
foo = [('a', 123), ('b', 345)]
def key_function(x):
return x[1]
sorted_list = sorted(foo, key_function)
print sorted_list
如您所见,sorted带有可选的第二个参数。该参数的目的是提供一个告诉已排序的事物如何排序的函数。您要做的就是分解列表中每个元组的信息以提供可以排序的值,因为您不能真正以任何有意义的方式对元组列表进行排序。
说得通?
也可以这样写:print sorted(foo, key=lambda (x,y): y)
lambda只是意味着没有名称的内联函数,它允许您以其他方式分解元组。
您可以通过执行print [y for (x,y) in sorted_list]来了解其工作原理
您甚至可以像这样重新定义键功能:
def key_function(x):
x,y = x
return y
顺便说一句,为了清楚起见,我只在括号中加了一个。如果您未定义函数,则逗号为元组构造函数。
您应该真正将其称为key_function,因为它没有排序,只是返回了键。
字典是通过键进行迭代的,因此,当您将字典传递给sorted时,会得到键的排序列表。按值对字典的项目元组进行排序,以获取已排序元组的列表。
sorted_charcount = sorted(charcount.items(), key=lambda item: item[1])
如果您使用的是Python 2.7+,则可以使用元组列表来初始化OrderedDict,这将保持项目元组的排序顺序。
他说:"我想将字符计数的结果整理到一个漂亮的列表中。"同样,"您不能对字典进行排序"是错误的,您可以对字典进行排序(正如您和其他答案所显示的那样),而字典只是没有排序。
固定我的答案
已有其他答案给出了这种确切的解决方案。
当我开始写答案时,该问题尚未得到解答。删除或保留答案没有多大意义,所以我保留了它。
charcount是dict(词典)。迭代字典会迭代其键,这就是sorted()导致键排序列表的原因。
您需要获取项目列表,然后按第二个值对其进行排序:
sorted(charcount.items(), key=lambda t: t[1])
sorted(charcount.items(), key=lambda item: item[1])
您将不得不使用charcount.items()而不是charcount