使用python解析文件时出现逻辑错误:KeyError:'O'

时间:2012-01-22 19:34:36

标签: python algorithm parsing python-3.x

所以我试图用一首诗打开一个文本文件,看看我能用每行文本文件中的字母拼写单词“GOOD”多少次,但是我收到以下错误:

Traceback (most recent call last):
  File "./soup.py", line 11, in <module>
    print( "\n".join( [("Case #%d: %d" % (i, parse(file[i]))) for i in range(1, len(file))]))
  File "./soup.py", line 7, in parse
    d['O'] /= 2
KeyError: 'O'

源:

#!/usr/bin/python

def parse(string):
    d = {'G' : 0, 'O' : 0, 'D' : 0}
    d = {s: string.count(s) for s in string if s in d } 
    d['O'] /= 2
    return min(d.values())

file = open("poem.txt").read().split('\n')
print( "\n".join( [("Case #%d: %d" % (i, parse(file[i]))) for i in range(1, len(file))]))

4 个答案:

答案 0 :(得分:4)

FWIW,我会用Counter对象写这个:

from collections import Counter

def spellcount(string, wanted):
    wanted_counts = Counter(wanted)
    have_counts = Counter(string)
    return min(have_counts[c]//wanted_counts[c] for c in wanted_counts)

wanted = "GOOD"
with open("poem.txt") as fp:
    for i, line in enumerate(fp):
        print("Case", i, ":", spellcount(line, wanted))

计数器表现为默认值,例如

>>> from collections import Counter
>>> Counter('GOOD')
Counter({'O': 2, 'G': 1, 'D': 1})
>>> Counter('GOOD')['i']
0

答案 1 :(得分:3)

你确定你的第7行读d ['O']吗?

错误消息表明它读取了d ['C']

问题是如果该行不包含'O'字符,则'O'将不在d中,这会产生错误。

第二次定义d将创建一个不包含“O”键的新词典。

def parse(string):
    d = {'G' : 0, 'O' : 0, 'D' : 0}
    d = {s: string.count(s) for s in string if s in d }
    try:
        d['O'] /= 2
    except KeyError:
        return 0
    return min(d.values())

file = open("test1.py").read().split('\n')
print( "\n".join( [("Case #%d: %d" % (i, parse(file[i]))) for i in range(1, len(file))]))

(您可能会发现在d中执行d = {s:string.count(s)for s}更有效率)

(我也喜欢使用collections.Counter的替代建议。但是,如果你对速度感兴趣,那么我的定时测量表明,对于一个1000万字符的字符串,制作Counter对象需要3秒,但只有0.012秒每次调用string.count)

答案 2 :(得分:1)

在字典理解中使用'GOD'代替string,因为并非每行都包含“O”。

def parse(string):
    d = {s: string.count(s) for s in 'GOD'}
    d['O'] /= 2
    return min(d.values())

答案 3 :(得分:0)

问题是,如果您遇到一条不计算“O”的行,则该密钥不会存在。您可以使用dict.get解决此问题。如果某个密钥不存在但返回其第二个参数,则dict.get不会引发异常,在这种情况下0

def parse(string):
    d = {s: string.count(s) for s in string if s in 'GOD'} 
    d['O'] = d.get('O', 0) / 2
    return min(d.values())

请注意,上面只匹配大写字母,如果你想要大写和小写,你可以这样做:

def parse(string):
    string = string.upper()
    d = {s: string.count(s) for s in string if s in 'GOD'} 
    d['O'] = d.get('O', 0) / 2
    return min(d.values())

修改

当然,使用d = {s: string.count(s) for s in 'GOD'}可以完全避免这个问题,也更简洁。我建议使用@ Gandaro的答案。