Excel CSV во вложенный словарь; Список Пониманий - PullRequest
2 голосов
/ 14 мая 2010

У меня есть файлы 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, если я пытаюсь распечатать «сотрудников» в оболочке, это может привести к сбою IDLE (примерно 1051 строк).

2. Удалить employee_id из внутреннего диктанта

Вторая проблема, я помещаю ее в словарь, индексированный по employee_id, со значением в качестве вложенного словаря всех значений - однако, employee_id также является ключом: значением внутри вложенного словаря, что немного лишний? Есть ли способ исключить его из внутреннего словаря?

3. Манипулировать данными в понимании

В-третьих, нам нужно сделать некоторые манипуляции с импортированными данными - например, все телефонные номера имеют неправильный формат, поэтому нам нужно сделать некоторое регулярное выражение там. Также нам нужно преобразовать manager_id в фактическое имя менеджера и его адрес электронной почты. Большинство менеджеров находятся в одном файле, в то время как другие находятся в CSV-файле external_contractors, который похож, но не совсем в том же формате - хотя я могу импортировать его в отдельный файл.

Являются ли эти два элемента вещами, которые можно выполнить в рамках понимания единого списка, или я должен использовать цикл for? Или многократное понимание работает? (пример кода будет действительно здорово здесь). Или в Python есть более разумный способ сделать это?

Ура, Victor

1 Ответ

4 голосов
/ 14 мая 2010

Ваша первая часть имеет одну простую проблему (которая может даже не быть проблемой). Вы вообще не обрабатываете столкновения клавиш (если только не собираетесь просто перезаписать).

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

Если вам гарантировано, что employee_id уникален, проблема не возникает.

2) Конечно, вы можете исключить это, но никакого реального вреда не причинено. На самом деле, особенно в python, если employee_id является строкой или int (или каким-либо другим примитивом), ссылка на внутренний dict и ключ фактически ссылаются на одно и то же. Они оба указывают на одно и то же место в памяти. Единственное дублирование в ссылке (что не так уж и много). Если вы беспокоитесь о потреблении памяти, вам, вероятно, нет необходимости.

3) Не пытайтесь сделать слишком много в одном понимании списка. Просто используйте цикл for после первого понимания списка.

Подводя итог, кажется, что вы действительно беспокоитесь о производительности повторения цикла дважды. Изначально не беспокойтесь о производительности. Проблемы с производительностью возникают из-за проблем алгоритма, а не из-за специфических языковых конструкций, таких как циклы и списки.

Если вы знакомы с нотацией Big O, то для понимания списка и цикла for (если вы решите это сделать) оба имеют Big O, равное O (n). Сложите их вместе, и вы получите 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'])
...