2010-05-14 79 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