创建字母直方图

0 投票
6 回答
6690 浏览
提问于 2025-04-18 01:03

我想创建一个直方图。
这是我的代码:

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 个回答

0

如果你想列出整个(仅限拉丁字母)字母表,你可以使用一个长度为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]
1

如果你想要有序的结果,那你就得使用一个有序字典。

在把字母放进字典之前,你还需要先把字母排序。看起来你想要不区分大小写的结果,所以我们需要把所有字母都转换成同一种大小写。

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
2

一个简单的答案是:

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]

这样会整洁很多。

3

使用一个有序字典,它会按照你放入的顺序来存储键。

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
3

只需使用 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())

撰写回答