我有一个包含员工记录的Excel CSV文件。像这样:
mail,first_name,surname,employee_id,manager_id,telephone_number
blah@blah.com,john,smith,503422,503423,+65(2)3423-2433
foo@blah.com,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上打印出“雇员”,它似乎会导致IDLE崩溃(大约有1051行)。
2。从内部字典中删除employee_id
第二个问题,我将它放入一个由employee_id索引的字典中,其值为所有值的嵌套字典 - 但是,employee_id也是一个键:嵌套字典中的值,这有点多余?有没有办法将它从内部字典中排除?
第3。在理解中操纵数据
第三,我们需要对导入的数据进行一些操作 - 例如,所有的电话号码都是错误的格式,所以我们需要在那里做一些正则表达式。此外,我们需要将manager_id转换为实际经理的姓名及其电子邮件地址。大多数管理员都在同一个文件中,而其他管理员使用的是外部协作者CSV,这种格式相似但格式不同 - 我可以将其导入单独的字典中。
这两项是否可以在单个列表理解中完成,或者我应该使用for循环?或多种理解有效吗? (示例代码在这里真的很棒)。或者在Python中有更聪明的方法吗?
干杯, 维克多
答案 0 :(得分:4)
你的第一部分有一个简单的问题(甚至可能不是问题)。您根本不处理关键冲突(除非您打算简单地覆盖)。
>>> dict([('a', 'b'), ('a', 'c')])
{'a': 'c'}
如果您保证employee_id
是唯一的,则不会出现问题。
2)当然你可以排除它,但没有真正的伤害。实际上,特别是在python中,如果employee_id是一个字符串或int(或其他一些原语),内部字典的引用和键实际上引用相同的东西。它们都指向内存中的相同位置。唯一的重复是参考(不是那么大)。如果你担心内存消耗,你可能不必这么做。
3)不要试图在一个列表理解中做太多。只需在第一个列表理解后使用for循环。
总而言之,听起来你真的很担心迭代循环两次的性能。 最初不要担心性能。性能问题来自算法问题,而不是像循环与列表推导这样的特定语言结构。
如果你熟悉Big O表示法,那么列表理解和for循环(如果你决定这样做)都有一个O(n)的大O.将它们加在一起就可得到O(2n),但正如我们从Big O表示法中所知,我们可以将其简化为O(n)。我在这里简化了很多,但重点是,你真的不必担心。
如果存在性能问题,请在编写代码后提出它们并使用代码分析器向自己证明。
对评论的回应
对于你的#2回复,python真的没有很多机制让一个衬里可爱和额外的时髦。这意味着强迫你简单地编写代码而不是将它们全部放在一行中。话虽这么说,仍然可以在一行中完成相当多的工作。我的建议是不要担心你可以在一行中添加多少代码。当它写出来时,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'])