2012-01-22 7 views
2

テキストファイルを詩で開き、テキストファイルに「GOOD」という単語を何度も綴ることができます各行が、私は次のエラーを取得:pythonでファイルを解析する際に論理エラーが発生しました:KeyError: 'O'

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))])) 
+0

「{c:dのcのstring.count(c)}」でカウントする必要があります。 –

答えて

3

は、あなたのライン7をd [ 'O']を読み込み、あなたは確かにいますか?

エラーメッセージは、問題が行が全く「O」文字が含まれない場合、「O」はDでなくなり、これはエラーを与えることであるD [「C」]

を読み出す示唆する。

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 = {S:Dでのsのためのstring.count(複数可)}行うにはそれがより効率的に見つけるかもしれない)

(私もcollections.Counterを使用しての代替案が大好きです。しかし、スピードに興味があるならば、私のタイミング測定によると、1000万の文字列の場合、Counterオブジェクトを作るのに3秒かかりますが、string.countには0.012秒しかかかりません)

+1

はい私は少し簡単にするためにコードを少し変更しました – Neo

+1

多くの文字があり、良いという言葉は実際に文でした。申し訳ありません。 – Neo

+0

'C'が存在しないので、 'd ['O']/= 2'は* KeyErrorを発生させません... – Gandaro

0

問題は、 'O'をカウントしない行に出会うと、そのキーは存在しません。これはdict.getを使って解決できます。 dict.getは、キーが存在しない場合は例外を発生させるが、この場合0には、2番目の引数を返していない:上記のは唯一のあなたは大文字と小文字の両方をしたい場合は、あなたが行うことができ、大文字と一致する

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'}を使用すると、完全に問題を回避し、あまりにもより簡潔です。私は@ガンダロの答えを使用することをお勧めします。

1

stringの代わりに'GOD'をご使用ください。すべての行に 'O'が含まれているわけではありません。

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

実際にあなたは 'GOD'に変更する必要があります;)、あなたは数えています。それ以外に、それは完璧です。 –

+0

ありがとう、そうです、それは不要です。私はそれを変えた。 – Gandaro

4

FWIW、私はこのカウンタオブジェクトを使用して記述します。

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)) 

カウンターは、例えば、defaultdictとして振る舞いを

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

+1あなたのソリューションは最高のDSMだと思っていますが、問題のポイントはキーエラー例外を処理する方法を学ぶことでした。とにかくあなたの役に立つポストに感謝 – Neo

+1

@ネオ:心配はありません!あなたがPythonでこれを行う方法と、あなたが持っているコードを与えて問題を解決する方法の両方が、知っておくと便利なことです。 – DSM

関連する問題