2011-04-20 121 views
2

我想爲文件取路徑,打開文件並讀取其中的數據。在此過程中,我想要統計字母表中每個字母的出現次數。嘗試除了在Python中

我讀過的和聽到的,使用try/except在這裏最好。我在這方面盡了最大的努力,但我只能計算出程序中字符串出現的位置,而不是文件內出現的位置。

我還沒有線索現在怎麼做到這一點,我的大腦已經開始傷害....這是我到目前爲止有:

import sys 
print "Enter the file path:" 
thefile = raw_input() 
f = open(thefile, "r") 
chars = {} 
for c in f: 
    try: 
     chars[c]+=1 
    except: 
     chars[c]=1 
print chars 

任何幫助將得到高度讚賞。謝謝。

編輯:我忘了說,我在一分鐘得到的結果說,整個文件是一個字符。該文件由「abcdefghijklmnopqrstuvwxyz」組成,結果輸出爲:{'「abcdefghijklmnopqrstuvwxyz」\ n':1},它不應該是。

回答

1

for c in f:語句正在逐行處理文件(這是文件對象上for操作的設計目的)。由於要處理它逐個字符,嘗試改變,爲:

data = f.read() 
for c in data: 

.read()方法讀取文件的全部內容複製到一個字符串,其分配到data,那麼for循環認爲每一個人該字符串的字符。

1

你幾乎在那裏,其實;你錯過的最重要的事情是你的c不是一個字符,而是一條線:迭代通過Python文件一次給你一條線。您可以通過添加另一個循環解決的問題:(整個文件讀入一個字符串也適用,作爲另一個答案中提到,如果你的文件足夠小,以適應在內存中)

print "Enter the file path:" 
thefile = raw_input() 
f = open(thefile, "r") 
chars = {} 
for line in f: 
    for c in line: 
     try: 
      chars[c]+=1 
     except: 
      chars[c]=1 
print chars 

雖然它確實在這種情況下工作,除非你真的試圖捕捉所有可能的錯誤,否則使用原始的except:並不是一個好主意。相反,使用except KeyError:

你想要做的事很常見,所以有一個Python字典方法和數據類型可以完全從你的代碼中刪除try/except。看看the setdefault methodthe defaultdict type。無論哪種,你基本上可以指定缺失值從0開始。

+0

謝謝大家的快速回復。 Nicholas,謝謝。它確實有效。 :) 即使沒有任何事件發生,我將如何去顯示所有出現的字母表的統計信息?例如,如果文件中包含文本「你好,你好嗎?」,我希望它顯示字母b出現0次,等等。 啊,setdefault方法和defaultdict類型能解決這個問題嗎? – Emlyn 2011-04-20 01:01:31

+1

不行,但你可以這樣做:'from string import ascii_letters; for ascii_letters中的字母:chars [letter] = 0'。這會給你A-Z,A-Z。 – 2011-04-20 01:04:03

+0

@埃姆林:尼古拉斯說了些什麼。但更簡單的方法來做同樣的事情是'chars = dict(zip(ascii_letters,[0] * len(ascii_letters)))'就像我在我更新的答案中顯示的那樣。 – 2011-04-20 01:08:13

4

稍微更簡潔的方法是這樣的:

from __future__ import with_statement 

from collections import defaultdict 

print "Enter the file path:" 
thefile = raw_input() 

with open(thefile, "r") as f: 
    chars = defaultdict(int) 

    for line in f: 
     for c in line: 
      chars[c] += 1 

    print dict(chars) 

這將使用defaultdict簡化計數過程,使用兩個循環,以確保我們無需將整個文件讀入內存,就可以單獨讀取每個字符,並使用with塊來確保文件已正確關閉。

編輯

爲了計算字母的直方圖,您可以使用此版本:

from __future__ import with_statement 

from string import ascii_letters 

print "Enter the file path:" 
thefile = raw_input() 

chars = dict(zip(ascii_letters, [0] * len(ascii_letters))) 

with open(thefile, "r") as f: 

    for line in f: 
     for c in line: 
      if c in ascii_letters: 
       chars[c] += 1 

for c in ascii_letters: 
    print "%s: %d" % (c, chars[c]) 

它使用得心應手string.ascii_letters不變,並顯示出一種巧妙的方法來建立空的字典同樣使用zip()

+0

使用'defaultdict(int)'會更快更短,因爲它不涉及每次調用Python函數。 – 2011-04-20 00:59:42

+0

@尼古拉斯:好點!我已編輯匹配。 – 2011-04-20 01:00:22

+0

嗯,運行時出現錯誤: Traceback(最近一次調用最後一次): 文件「********************」,第14行,在 chars [c] + = 1 KeyError:'a' 我對Python很新穎,所以需要一段時間才能沉入其中。現在是凌晨2點! – Emlyn 2011-04-20 01:08:26

0

讓我們把一個更Python的方式爲PEP8的緣故:包括

import collections 
with open(raw_input(), 'rb') as f: 
    count = collections.Counter(f.read()) 
    print count 

電池! :)

+0

集合僅在python> = 2.7時可用 – 2011-04-20 01:06:18

+0

@mike:我不認爲我們在這裏討論生產環境,所以我認爲這不是問題。 – ktdrv 2011-04-20 01:09:33