2015-12-03 35 views
2

[任務]Python 2中無法獲得的鍵和值(字典和元組)

編寫一個程序通過一個文本文件的讀取和計算出的一天的小時的分佈對於每個消息。您可以通過查找時間,然後使用冒號第二次拆分字符串,從「發件人」行拉出小時。行的文本文件的

例子:

「從[email protected]週六1月5日9時14分十六秒2015」

一旦你已經積累了各計數小時,打印出計數,按小時排序,如下所示。

[預期結果]

04 3 
06 1 
07 1 
09 2 
10 3 
11 6 
14 1 
15 2 
16 4 
17 2 
18 1 
19 1 

這意味着,我需要拉出「九時14分16秒」部分,然後拉出小時「09」一次。

我會用 '#' 評論什麼,我已經做了以下

[我的代碼]

name = raw_input("Enter file:") 
if len(name) < 1 : name = "mbox-short.txt"  #if nothing is entered by user, it goes straight to the desired file 
handle = open(name, 'r')  # open and read the file 
count = dict()  # initialise count to a empty dictionary 
for text in handle:  #for loop to loop through lines in the file 
    text = text.rstrip()  #r.strip() to to remove any newline "\n" 
    if not text.startswith('From '): continue  # find lines that starts with "From " 
    text = text.split()   #split the line into list of words 
    line = text[5]    #time is located at the [5] index 
    time = line.split(':')  #split once more to get the hour 
    hour = time[0]   #hour is on the [0] index  
    count[hour] = count.get(hour, 0) + 1 
    print count   

[我的結果]

{'09': 1} ← Mismatch 
{'09': 1, '18': 1} 
{'09': 1, '18': 1, '16': 1} 
{'09': 1, '18': 1, '16': 1, '15': 1} 
{'09': 1, '18': 1, '16': 1, '15': 2} 
{'09': 1, '18': 1, '16': 1, '15': 2, '14': 1} 
{'09': 1, '18': 1, '16': 1, '15': 2, '14': 1, '11': 1} 
{'09': 1, '18': 1, '16': 1, '15': 2, '14': 1, '11': 2} 
{'09': 1, '18': 1, '16': 1, '15': 2, '14': 1, '11': 3} 
(deleted portion of the result) 
{'09': 2, '18': 1, '16': 1, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1} 
{'09': 2, '18': 1, '16': 1, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1, '17': 1} 
{'09': 2, '18': 1, '16': 1, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1, '17': 2} 
{'09': 2, '18': 1, '16': 2, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1, '17': 2} 
{'09': 2, '18': 1, '16': 3, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1, '17': 2} 
{'09': 2, '18': 1, '16': 4, '15': 2, '14': 1, '11': 6, '10': 3, '07': 1, '06': 1, '04': 3, '19': 1, '17': 2} 

有人可以幫助我放哪兒我錯了?我正朝着正確的方向前進嗎? 感謝任何意見和建議,即時編程新手請溫柔和抱歉的任何格式錯誤。

+0

我不明白你輸出的問題是什麼,你能更明確嗎?順便說一下,請查看[Counter](https://pymotw.com/3/collections/counter.html)模塊,看起來它可能非常合適。 – iodbh

回答

0

日期時間以來總是具有相同的格式,你可以用假設法:

your_string[-13:11] # your hour 

其中your_string是一個粘貼,但每一個文字,其中將包含完整的日期時間將是有效的進行此項操作。

1

刪除print count,並在年底和外循環加上這些行:

for key in sorted(count.keys()): 
    print key, count[key] 
+0

@明爲你做了這個工作嗎? –

0

我覺得如果你從字面上想要的輸出,而不是「打印計數」你到底需要(外循環) :

for a in sorted(count.keys()): 
    print a,count[a] 
+0

我也可以使用 爲k,v在排序(計數。物品()): \t print k,v – ming

0

您的問題是你打印一本字典和詞典不能(通過其鍵值實際上他們,但不是那麼它是一個有爭議的問題)在Python排序。

如前所述,您可以在打印結果之前通過排序字典鍵來解決此問題。就個人而言,我不確定這是最好的解決方案。

原因是你正在處理數字。更重要的是,你正在處理[0,23]範圍內的數字。這從字面上尖叫「使用列表!」對我來說。 :-)

因此,而不是使用字典()的,請嘗試使用:

# count = dict() 
count = [0] * 24 

這將創建一個列表有24個項目,與指數從0到23。

現在,你從你的字符串解析得到什麼都是字符串爲好,所以你需要將它們轉換爲數字:

# count[hour] = count.get(hour, 0) + 1 
count[int(hour)] += 1 

注意如何讓這不能被轉換爲整數或沒有按」一小時t落入0..23的範圍內可以使用字典,但會失敗,並顯示預先初始化的列表。這實際上是很好的:代碼接收不好的輸入,並使用它來產生不良的輸出而不會引發投訴,這是糟糕的代碼。當然,只拋出異常的代碼也不是很好的代碼,但它是朝正確方向邁出的一步。

當然,還會出現另一個問題:如果您打印字典,則會打印鍵和值。如果您打印一份清單,只打印數值。因此,我們需要輸出的代碼更改爲:

for hour, amount in enumerate(count): 
    print hour, ':', amount 

下一點我想在你的代碼解決的是:你絕對相信你的電子郵件地址會包含空格?總有你的代碼將再次遇到這樣一行以下機會:

From: "Bob Fisher" <[email protected]> Sat Jan 5 09:14:16 2015 

從本質上講,你的字符串看起來像它的尾巴比它的頭更經常和可預測的格式。這意味着它會更可靠的使用略有不同的語法來檢索時間:

# line = text[5] 
line = text[-2] # We take 2nd element from the end of string instead 

它可能是更通用的使用正則表達式,但是這是我將離開這裏發現了一個更高級的主題:如果你知道正則表達式,你就可以很容易地做到這一點,如果你不這樣做,你會更好地進行適當的介紹,而不是我可以在這裏拼湊的任何東西。

另一個挑剔:我注意到你沒有關閉你的文件句柄。這不是一個大問題,因爲你的程序終止,任何仍然打開的文件句柄將被自動關閉。然而,在一個更大的項目中,這可能會導致問題。您的代碼可能會被其他代碼調用,如果您的代碼生成異常並且此異常由調用者處理或抑制,則文件句柄將保持打開狀態。重複次數足夠多,並且程序將超出操作系統限制以獲得最大打開文件數量。

所以我會建議使用稍有不同的語法來打開文件:

with open(name, 'r') as handle: 
    for text in handle: 
     # ... 

這種語法的優勢在於「用」會正確地關閉文件句柄,無論在它下面的代碼會發生什麼。即使發生異常,文件仍將被正確關閉。

而且到目前爲止的代碼看起來像:

name = raw_input("Enter file:") 
if not name: name = "mbox-short.txt" # cleaner check for empty string 
count = [0] * 24 # use pre-initialized list instead of dict 
with open(name, 'r') as handle: # use safer syntax to open files 
    for text in handle: 
     text = text.rstrip() 
     if not text.startswith('From '): continue 
     text = text.split() 
     line = text[-2] # use 2nd item from the end, just to be safe 
     time = line.split(':') 
     hour = int(time[0]) # we treat hour as integer 
     count[hour] += 1 # nicer looking 
for hour, amount in enumerate(count): 
    if amount: # Only print hours with non-zero counters 
     print hour, ':', amount 

現在,有一些方法可以減小它的尺寸至少一半(甚至更多),但我一直在試圖把一切都簡單,忠於原始代碼的精神。

+0

哦,我這就是一個很長的,我喜歡學習模仿,但是,感謝您的幫助,無論如何,真的很感激它 – ming

0
import re 
import collections 

name = raw_input("Enter file:") 
if not name: name = "mbox-short.txt" 

with open(name) as handle: 
    hours = re.findall(r'^From .*(\d{2}):\d{2}:\d{2}', handle.read(), re.M) 

count = sorted(collections.Counter(hours).items(), key=lambda x: int(x[0])) 

for h, c in count: 
    print h, c