创建字母直方图
我想创建一个直方图。
这是我的代码:
def histogram(s):
d = dict()
for c in s:
if c not in d:
d[c] = 1
else:
d[c] += 1
return d
def print_hist(h):
for c in h:
print c, h[c]
运行后给我这个结果:
>>> h = histogram('parrot')
>>> print_hist(h)
a 1
p 1
r 2
t 1
o 1
但是我想要这个结果:
a: 1
o: 1
p: 1
r: 2
t: 1
所以我该怎么做才能让我的直方图按字母顺序排列,并且对大小写敏感(也就是说"a"和"A"算是一样的),同时列出整个字母表(也就是那些在字符串中没有出现的字母显示为零)呢?
6 个回答
如果你想列出整个(仅限拉丁字母)字母表,你可以使用一个长度为26的列表:
hist = [0] * 26
for c in s.lower():
hist[orc(c) - ord('a')] += 1
这样就能得到你想要的输出:
for x in range(26):
print chr(x), ":", hist[x]
如果你想要有序的结果,那你就得使用一个有序字典。
在把字母放进字典之前,你还需要先把字母排序。看起来你想要不区分大小写的结果,所以我们需要把所有字母都转换成同一种大小写。
from collections import OrderedDict as od
import string
def histogram(s):
首先,我们需要创建一个包含所有小写字母的字典。我们引入了一个叫做string的库,它会给我们提供一个字母表,但我觉得它包含了所有的小写字母和一些其他字符,所以我们只需要用string.lowercase中的前26个字母。
d = od()
for each_letter in string.lowercase[0:26]:
d[each_letter] = 0
一旦字典创建好了,我们只需要遍历这个已经转换成小写的单词。请注意,如果单词里有数字或空格,这个过程可能会出错。你可以选择是否要在字典中测试或添加数字和空格。避免出错的一种方法是尝试添加一个值。如果这个值不在字典里,就直接忽略它。
for c in s.lower():
try:
d[c] += 1
except ValueError:
pass
return d
一个简单的答案是:
import string
for letter in string.ascii_lowercase:
print letter, ': ', h.lower().count(letter)
(这样做效率很低,因为你要遍历字符串26次)
也可以使用一个叫做 Counter
的工具。
from collections import Counter
import string
cnt = Counter(h.lower())
for letter in string.ascii_lowercase:
print letter, ': ', cnt[letter]
这样会整洁很多。
使用一个有序字典,它会按照你放入的顺序来存储键。
from collections import OrderedDict
import string
def count(s):
histogram = OrderedDict((c,0) for c in string.lowercase)
for c in s:
if c in string.letters:
histogram[c.lower()] += 1
return histogram
for letter, c in count('parrot').iteritems():
print '{}:{}'.format(letter, c)
结果:
a:1
b:0
c:0
d:0
e:0
f:0
g:0
h:0
i:0
j:0
k:0
l:0
m:0
n:0
o:1
p:1
q:0
r:2
s:0
t:1
u:0
v:0
w:0
x:0
y:0
z:0
只需使用 collections.Counter
就可以解决这个问题,除非你真的想自己写一个:
>>> import collections
>>> c = collections.Counter('parrot')
>>> sorted(c.items(), key=lambda c: c[0])
[('a', 1), ('o', 1), ('p', 1), ('r', 2), ('t', 1)]
编辑:正如评论者指出的,你最后一句话表明你想要获取所有字母中在你的单词中没有出现的字母的数据。Counter
也很适合这个,因为文档中提到:
Counter 对象有一个字典的接口,除了对于缺失的项目,它会返回零计数,而不是抛出
KeyError
。
所以你可以简单地遍历像 string.ascii_lowercase
这样的内容:
>>> import string
>>> for letter in string.ascii_lowercase:
... print('{}: {}'.format(letter, c[letter]))
...
a: 1
b: 0
c: 0
d: 0
e: 0
f: 0
g: 0
h: 0
i: 0
j: 0
k: 0
l: 0
m: 0
n: 0
o: 1
p: 1
q: 0
r: 2
s: 0
t: 1
u: 0
v: 0
w: 0
x: 0
y: 0
z: 0
最后,与其实现一些复杂的代码来合并大小写字母的结果,不如先对你的输入进行标准化:
c = collections.Counter('PaRrOt'.lower())