2013-11-02 216 views
0

我正在寫一個Python 3腳本,並製表林業木材計數可變長度命令的元組。處理與嘗試......除了

工人將電臺種類,平均直徑,並且在每棵樹的日誌高度它們標記爲電腦操作員。然後,計算機操作員將進入一個命令,例如這樣的:

OAK 14 2 

這意味着該方案應增加直徑14英寸和兩個日誌高度橡樹計數。

但是,工作人員有時也會同時呼叫同一類型的樹中的一個以上。所以程序也必須能夠處理這個命令:

OAK 16 1 2 

這將意味着我們正在增加兩個計數。

我有解析器設置方式是這樣的:

key=cmdtup[0]+"_"+cmdtup[1]+"_"+cmdtup[2] 
     try: 
      trees[key]=int(trees[key])+int(cmdtup[3]) 
     except KeyError: 
      trees[key]=int(cmdtup[3]) 
     except IndexError: 
      trees[key]=int(trees[key])+1 

如果程序命令來存儲它之前沒有存儲一棵樹,一個KeyError異常會熄滅,處理程序將設置字典輸入,而不是增加它。如果省略第三個參數,一個IndexError將提高,而處理器將它視爲如果第三個參數是發生1

問題,但是,如果我們在一次這兩種情況下,該計劃還沒有聽說過橡樹,並且運營商沒有指定計數。 KeyError會關閉,但會自動生成一個IndexError,並且在異常處理程序中發生異常時,Python不會喜歡它。

我想最簡單的方法是簡單地刪除一個或另一個不同之處,並有其功能可以用另一種方式來完成。不過,我想知道是否有更優雅的Pythonic方法來完成此任務。在那兒?

+0

不要欺負你的程序用戶強迫他們在cmd.exe中輸入參數,例如。這是殘酷的。創建一些前端。 – Artur

+0

它不能通過argv工作。在我發佈的位之上有一個輸入循環。另外,我是最終用戶。 – Schilcote

+0

有什麼答案可以接受? – uselpa

回答

0

最後,最好的方法是簡單地刪除IndexError處理程序,將cmdtup更改爲列表並插入以下代碼:

if len(cmdtup) >= 3: 
    cmdtup.append(1) 
0

我會做這樣的事情:

def parse(cmd, trees): 
    res = cmd.split() # split the string by spaces, yielding a list of strings 
    if len(res) == 3: # if we got 3 parameters, set the fourth to 1 
     res.append(1) 
    for i in range(1,4): # convert parameters 1-3 to integers 
     res[i] = int(res[i]) 
    key = tuple(res[x] for x in range(3)) # convert list to tuple, as lists cannot be dictionary indexes 
    trees[key] = trees.get(key,0) + res[3] # increase the number of entries, creating it if needed 

trees={} 

# test data 
parse("OAK 14 2", trees) 
parse("OAK 16 1 2", trees) 
parse("OAK 14 2", trees) 
parse("OAK 14 2", trees) 

# print result 
for tree in trees: 
    print(tree, "=", trees[tree]) 

產生

('OAK', 16, 1) = 2 
('OAK', 14, 2) = 3 

一些注意事項:

  • 沒有的錯誤處理,你應該處理的情況下,當值應該是一個數字是不是或輸入是錯誤的任何其他方式
  • 而不是字符串,我用的元組作爲字典指數
0

你可以使用collections.Counter,如果該鍵不在字典中返回0,而不是一個KeyError

Counter Documentation:

Counter對象都有一本字典的接口,除了它們返回一個零計數丟失物品而不是引發一個KeyError

事情是這樣的:

from collections import Counter 

counts = Counter() 

def update_counts(counts, cmd): 
    cmd_list = cmd.split() 
    if len(cmd_list) == 3: 
     tree = tuple(cmd_list) 
     n = 1 
    else: 
     *tree, n = tuple(cmd_list) 
    counts[tree] += n 

相同的註釋適用於uselpa的回答。 Counter的另一個好處是,如果你想,例如,看每週計數,你只需要做一些事情,如sum(daily_counts)

Counter作品甚至更好,如果你從命令的列表開始:

from collections import Counter 
from itertools import repeat 

raw_commands = get_commands() # perhaps read a file 
command_lists = [c.split() for c in raw_commands] 

counts = Counter(parse(command_lists)) 

def parse(commands): 
    for c in commands: 
     if len(c) == 3: 
      yield tuple(c) 
     elif len(c) == 4 
      yield from repeat(tuple(c[0:2]), times=c[3]) 

從那裏,你可以使用update_counts功能上面添加新的樹木,你就可以開始在另一個文本收集命令文件,然後在第二天,下一週等生成第二個Counter對象。