2010-05-14 9 views
2

J'ai un fichier Excel CSV avec les dossiers des employés en eux. Quelque chose comme ceci:Excel CSV dans le dictionnaire imbriqué; Liste compréhensions

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 
.... 

J'utilise DictReader de mettre cela dans un dictionnaire imbriqué:

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

est-ce qui précède la bonne façon de le faire - il ne fonctionne pas, mais est-ce le droit Façon? Quelque chose de plus efficace? En outre, la chose amusante est, dans IDLE, si j'essaie d'imprimer des «employés» à l'interpréteur de commande, il semble provoquer le blocage de IDLE (il y a environ 1051 lignes).

2. Retirez employee_id de dict intérieur

La deuxième question d'émission, je mets dans un dictionnaire indexé par employee_id, avec la valeur comme un dictionnaire imbriqué de toutes les valeurs - cependant, employee_id est aussi une clé: valeur dans le dictionnaire imbriqué, qui est un peu redondant? Est-il possible de l'exclure du dictionnaire interne?

3. Manipuler les données dans la compréhension

Troisièmement, nous devons faire quelques manipulations pour les données importées - par exemple, tous les numéros de téléphone sont dans le mauvais format, nous devons donc faire un peu regex là. En outre, nous devons convertir manager_id en un nom de gestionnaire réel, et leur adresse e-mail. La plupart des gestionnaires sont dans le même fichier, tandis que d'autres sont dans un CSV external_contractors, qui est similaire mais pas tout à fait le même format - je peux importer cela dans une dict séparée.

-ce que ces deux objets des choses qui peuvent être fait dans la compréhension de la liste unique, ou devrais-je utiliser une boucle? Ou est-ce que plusieurs compréhensions fonctionnent? (code exemple serait vraiment génial ici). Ou y a-t-il une façon plus intelligente de le faire en Python?

Cheers, Victor

Répondre

4

Votre première partie a une simple question (qui pourrait même ne pas être un problème). Vous ne gérez pas du tout les collisions de clés (sauf si vous avez l'intention de simplement les remplacer).

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

Si vous êtes assuré que employee_id est unique, il n'y a pas un problème cependant.

2) Bien sûr, vous pouvez l'exclure, mais pas fait du tort réel. En fait, surtout en python, si employee_id est une chaîne ou int (ou une autre primitive), la référence du dict interne et la clé font référence à la même chose. Ils pointent tous les deux vers le même endroit en mémoire. La seule duplication est dans la référence (qui n'est pas si grande). Si vous êtes préoccupé par la consommation de mémoire, vous n'avez probablement pas à le faire.

3) Ne pas essayer d'en faire trop dans une compréhension de la liste. Utilisez simplement une boucle for après la première compréhension de la liste.

Pour résumer, on dirait que vous êtes vraiment inquiet au sujet de la performance de itérer sur la boucle deux fois. Ne vous inquiétez pas des performances au départ. Les problèmes de performances proviennent de problèmes d'algorithmes, pas de constructions de langage spécifiques comme pour les boucles par rapport aux compréhensions de liste.

Si vous êtes familier avec la notation Big O, la compréhension de la liste et boucle après (si vous décidez de le faire) ont tous deux un grand O de O (n).Ajoutez-les ensemble et vous obtenez O (2n), mais comme nous le savons de la notation Big O, nous pouvons simplifier cela à O (n). J'ai beaucoup simplifié ici, mais le fait est que vous n'avez vraiment pas besoin de vous inquiéter.

En cas de problèmes de performances, augmentez-les après avoir écrit le code et faites-le vous-même à l'aide d'un profileur de code.

réponse aux commentaires

Quant à votre # 2 réponse, python n'a vraiment pas beaucoup de mécanismes pour faire une liners de chouettes mignon et extra. Il est destiné à vous forcer à écrire simplement le code par rapport à coller tout en une ligne. Cela étant dit, il est toujours possible de faire un peu de travail en une ligne. Ma suggestion est de ne pas s'inquiéter de la quantité de code que vous pouvez coller dans une ligne. Python semble beaucoup plus beau (IMO) quand il est écrit, pas coincé dans une ligne.

Quant à votre # 1 réponse, vous pouvez essayer quelque chose comme ceci:

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

Quant à votre réponse n ° 3, ne sais pas ce que vous cherchez et ce sur les numéros de téléphone que vous souhaitez de fixer, mais ... cela peut vous donner un nouveau départ:

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

heya, @xyld: Merci pour la réponse détaillée =). 1. L'employee_id est garanti d'être unique, d'après ce qu'on m'a dit. Cependant, juste pour référence, quelle est la façon recommandée de gérer cela? Des exceptions? (N'importe quel code d'exemple ici serait génial). 2. Bien, si c'est juste un peu de mémoire supplémentaire, alors je suppose que ce n'est pas un gros problème. Je pensais juste qu'il pourrait y avoir une manière intelligente en Python de l'exclure du dict interne. – victorhooi

+0

3. Hmm, oui, vous avez raison, l'optimisation prématurée est la racine de tous les maux, et tout cela * sourit *. Et oui, c'est juste linéaire, donc je suis sûr que ça ira. Je suis toujours en train d'essayer de comprendre les choses, est-il possible d'en utiliser un pour faire un regex remplacer sur telephone_number, et les recherches pour le manager? – victorhooi

+0

@victorhooi vous êtes trop accroché sur la compréhension de la liste, je pense. Utilisez simplement une boucle for. La compréhension de la liste devrait naturellement figurer dans le code pour le rendre plus propre, et pas seulement pour le ** plaisir **. IMO – dlamotte