【问题标题】:Excel CSV into Nested Dictionary; List ComprehensionsExcel CSV 到嵌套字典中;列出理解
【发布时间】:2011-02-19 08:28:34
【问题描述】:

我有一个 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也是嵌套字典中的key:value,这有点多余的?有没有办法从内部字典中排除它?

3.在理解中处理数据

第三,我们需要对导入的数据进行一些操作——例如,所有电话号码的格式都错误,所以我们需要在那里做一些正则表达式。此外,我们需要将 manager_id 转换为实际经理的姓名和他们的电子邮件地址。大多数经理都在同一个文件中,而其他经理则在 external_contractors CSV 中,格式相似但不完全相同 - 我可以将其导入到单独的字典中。

这两项是否可以在单个列表理解中完成,或者我应该使用 for 循环?还是多重理解有效? (示例代码在这里真的很棒)。或者在 Python 中有更聪明的方法吗?

干杯, 维克多

【问题讨论】:

    标签: python csv list-comprehension


    【解决方案1】:

    您的第一部分有一个简单的问题(甚至可能不是问题)。您根本不处理键冲突(除非您打算简单地覆盖)。

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

    如果您保证 employee_id 是唯一的,那么就没有问题。

    2) 当然可以排除它,但不会造成真正的伤害。实际上,尤其是在 python 中,如果employee_id 是字符串或int(或其他一些原语),则内部dict 的引用和键实际上引用了相同的东西。它们都指向内存中的同一个点。唯一的重复是在参考中(不是那么大)。如果您担心内存消耗,您可能不必担心。

    3) 不要试图在一个列表理解中做太多事情。只需在第一个列表理解之后使用 for 循环。

    总而言之,听起来您真的很担心循环迭代两次的性能。 一开始不要担心性能问题。性能问题来自算法问题,而不是特定的语言结构,例如 for 循环与列表推导式。

    如果您熟悉大 O 表示法,则列表推导和 for 循环之后(如果您决定这样做)都具有 O(n) 的大 O。将它们加在一起,得到 O(2n),但正如我们从大 O 表示法中知道的那样,我们可以将其简化为 O(n)。我在这里简化了很多,但重点是,你真的不用担心。

    如果存在性能问题,请在编写代码后提出并使用代码分析器向自己证明。

    响应 cmets

    至于您的#2 回复,python 确实没有很多机制可以使 one liner 变得可爱和时髦。它的目的是强迫你简单地写出代码而不是把它全部放在一行中。话虽如此,仍然可以在一行中完成相当多的工作。我的建议是不要担心你可以在一行中粘贴多少代码。 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'])
    

    【讨论】:

    • 嘿,@xyld:感谢您的详细回复=)。 1. 据我所知,employee_id 保证是唯一的。但是,仅供参考,推荐的处理方法是什么?例外? (这里的任何示例代码都很棒)。 2. 很公平,如果只是一些额外的内存,那么我想这没什么大不了的。我只是认为 Python 中可能有一种聪明的方法可以将其从内部字典中排除。
    • 3.嗯,是的,你是对的,过早的优化是万恶之源,以及所有咧嘴笑。是的,它只是线性的,所以我相信它会没事的。不过,我仍在努力理解理解,有没有办法使用一种方法对电话号码进行正则表达式替换,并查找经理?
    • @victorhooi 你太沉迷于我认为的列表理解。只需使用 for 循环。列表推导应该自然而然地出现在代码中,使其看起来更简洁,而不仅仅是为了有趣。海事组织
    • 很公平,是的,我现在正在使用 for 循环 =)。感谢您的所有帮助。
    猜你喜欢
    • 1970-01-01
    • 2018-04-15
    • 2021-02-23
    • 2021-07-24
    • 2017-11-27
    • 2018-08-23
    • 2017-12-30
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多