2010-05-14 82 views
2

我有一個Excel CSV文件,其中包含員工記錄。事情是這樣的:Excel CSV嵌入字典;列表解析

mail,first_name,surname,employee_id,manager_id,telephone_number 
[email protected],john,smith,503422,503423,+65(2)3423-2433 
[email protected],george,brown,503097,503098,+65(2)3423-9782 
.... 

我使用DictReader把這個變成一個嵌套的字典:

import csv 
gd_extract = csv.DictReader(open('filename 20100331 original.csv'), dialect='excel') 
employees = dict([(row['employee_id'], row) for row in gp_extract]) 

是做正確的方式上面 - 它的工作,但它是正確的辦法?更高效的東西?另外,有趣的是,在IDLE中,如果我試圖在shell中打印「employees」,似乎會導致IDLE崩潰(大約有1051行)。

2.從內部字典

第二個問題的問題刪除EMPLOYEE_ID,我把它變成按employee_id索引的字典,以該值爲所有值的嵌套字典 - 然而,EMPLOYEE_ID是還有一個關鍵:嵌套字典中的值,這有點多餘?有沒有辦法將它從內部字典中排除?

3.在修真操縱數據

第三,我們需要做一些操作,以導入的數據 - 例如,所有的電話號碼都在錯誤的格式,所以我們需要做一些正則表達式那裏。另外,我們需要將manager_id轉換爲實際經理的姓名和他們的電子郵件地址。大多數經理都在同一個文件中,而其他人在外部合同CSV中,這是相似的,但格式不盡相同 - 我可以將其導入到單獨的字典中。

這兩個項目可以在單個列表理解中完成,還是應該使用for循環?或者多重理解是否奏效? (示例代碼在這裏真的很棒)。或者Python有更聰明的方法嗎?

乾杯, 維克多

回答

4

你的第一部分有一個簡單的問題(這甚至可能不會是一個問題)。你根本不處理關鍵衝突(除非你打算簡單覆蓋)。

>>> dict([('a', 'b'), ('a', 'c')]) 
{'a': 'c'} 

如果你保證employee_id是獨一無二的,沒有問題,但。

2)當然你可以排除它,但沒有真正的傷害。實際上,特別是在python中,如果employee_id是一個字符串或int(或其他原語),則內部字典的引用和鍵實際上引用相同的東西。他們都指向記憶中的同一個地方。唯一的重複是在參考(這不是那麼大)。如果你擔心內存消耗,你可能不需要。

3)不要試圖在一個列表理解中做太多。在第一個列表理解之後使用for循環。

總而言之,這聽起來像你真的擔心迭代循環兩次的性能。 最初不要擔心性能。性能問題來自算法問題,而不是像循環vs列表解析那樣的特定語言結構。

如果您熟悉Big O符號,則列表理解和循環之後(如果您決定這樣做)都具有O(n)的大O.將它們加在一起就可以得到O(2n),但正如我們從Big O符號中所知道的那樣,我們可以將它簡化爲O(n)。我在這裏簡化了很多,但重點是,你真的不需要擔心。

如果存在性能方面的問題,請在編寫代碼並將其用代碼分析器證明給自己後提出。

迴應評論

至於你的#2回答,蟒蛇真的沒有很多的機制使得一個襯墊可愛的和額外的時髦。這意味着強迫你簡單地編寫代碼,並將其全部保存在一行中。話雖如此,仍然有可能在一條線上做相當多的工作。我的建議是不用擔心可以在一行中粘貼多少代碼。當它寫出來時,Python看起來更漂亮(IMO),而不是堵塞在一行中。

至於你的#1的回覆,你可以嘗試這樣的事:

employees = {} 
for row in gd_extract: 
    if row['employee_id'] in employees: 
     ... handle duplicates in employees dictionary ... 
    else: 
     employees[row['employee_id']] = row 

至於你的#3的回覆,你想不知道你在尋找什麼有關電話號碼修復,但...這可能會給你一個開始:

import re 
retelephone = re.compile(r'[-\(\)\s]') # remove dashes, open/close parens, and spaces 
for empid, row in employees.iteritems(): 
    retelephone.sub('',row['telephone']) 
+0

部屋, @xyld:感謝您的詳細答覆=)。 1.根據我所告知的,employee_id保證是唯一的。但是,僅供參考,處理此問題的推薦方法是什麼?例外? (這裏的任何示例代碼都很棒)。 2.足夠公平,如果它只是一些額外的記憶,那麼我認爲它不是什麼大事。我只是認爲在Python中可能有一種聰明的方式將其從內部字典中排除。 – victorhooi 2010-05-14 03:48:18

+0

3.嗯,是的,你是對的,不成熟的優化是所有邪惡的根源,所有*咧嘴*。是的,這只是線性的,所以我相信它會沒事的。儘管如此,我還是試圖讓自己的頭腦理解,有沒有辦法用一個在telephone_number上做一個正則表達式替換,以及經理的查找? – victorhooi 2010-05-14 03:48:46

+0

@victorhooi你對我認爲的列表理解太掛了。只需使用for循環。清單理解應該自然地出現在代碼中,使其看起來更清晰,而不僅僅是**有趣**。國際海事組織 – dlamotte 2010-05-14 12:43:06