2009-12-17 7 views
9

J'ai un projet de conversion d'une base de données en une autre. L'une des colonnes de base de données d'origine définit la catégorie de la ligne. Cette colonne doit être mappée à une nouvelle catégorie dans la nouvelle base de données.Mappage plusieurs-à-un Python (création de classes d'équivalence)

Par exemple, supposons que les catégories originales sont: parrot, spam, cheese_shop, Cleese, Gilliam, Palin

Maintenant, c'est un peu bavard pour moi, et je veux avoir ces lignes classées comme sketch, actor - C'est, définir tous les croquis et tous les acteurs comme deux classes d'équivalence.

>>> monty={'parrot':'sketch', 'spam':'sketch', 'cheese_shop':'sketch', 
'Cleese':'actor', 'Gilliam':'actor', 'Palin':'actor'} 
>>> monty 
{'Gilliam': 'actor', 'Cleese': 'actor', 'parrot': 'sketch', 'spam': 'sketch', 
'Palin': 'actor', 'cheese_shop': 'sketch'} 

C'est tout à fait awkward- je préférerais avoir quelque chose comme:

monty={ ('parrot','spam','cheese_shop'): 'sketch', 
     ('Cleese', 'Gilliam', 'Palin') : 'actors'} 

Mais cela, bien sûr, définit le uplet entier comme une clé:

>>> monty['parrot'] 

Traceback (most recent call last): 
    File "<pyshell#29>", line 1, in <module> 
    monty['parrot'] 
KeyError: 'parrot' 

Toute idée comment créer un dictionnaire de plusieurs-à-un élégant en Python?

Merci,

Adam

+1

Découvrez cette élégante [réponse] (http://stackoverflow.com/a/11105962/355230) à une question similaire. – martineau

Répondre

11

Il me semble que vous avez deux préoccupations. Tout d'abord, comment exprimez-vous votre mapping à l'origine, c'est-à-dire comment tapez-vous le mapping dans votre fichier new_mapping.py. Deuxièmement, comment fonctionne le mappage pendant le processus de re-mappage. Il n'y a pas de raison pour que ces deux représentations soient les mêmes.

Commencez par la mise en correspondance vous aimez:

monty = { 
    ('parrot','spam','cheese_shop'): 'sketch', 
    ('Cleese', 'Gilliam', 'Palin') : 'actors', 
} 

puis le convertir en la mise en correspondance dont vous avez besoin:

working_monty = {} 
for k, v in monty.items(): 
    for key in k: 
     working_monty[key] = v 

production:

{'Gilliam': 'actors', 'Cleese': 'actors', 'parrot': 'sketch', 'spam': 'sketch', 'Palin': 'actors', 'cheese_shop': 'sketch'} 

puis utilisez working_monty pour faire le travail .

+1

+1 Merci beaucoup. Je suppose qu'il n'y a pas de type natif python pour ce travail; Pensez-vous qu'il devrait y en avoir un? –

+0

ne pouvons-nous pas avoir une référence en tant que valeur dans la paire (clé, valeur) plutôt que de stocker la chaîne réelle? Depuis le non. des clés sont significativement plus grandes que le non. de valeurs, cela permettrait d'économiser beaucoup d'espace. Y a-t-il un moyen de faire cela? – ishan3243

1
>>> monty={ ('parrot','spam','cheese_shop'): 'sketch', 
     ('Cleese', 'Gilliam', 'Palin') : 'actors'} 

>>> item=lambda x:[z for y,z in monty.items() if x in y][0] 
>>> 
>>> item("parrot") 
'sketch' 
>>> item("Cleese") 
'actors' 

Mais laissez-moi vous dire, il sera lent que la normale seul dictionnaire à l'un.

+0

Slow-ish, mais sur le côté positif ne nécessite pas une structure de données secondaire persistante. Pourrait être accéléré dans une certaine mesure en n'étant pas écrit comme un lambda et en utilisant une compréhension de la liste. – martineau

4

Vous pouvez passer outre indexeur de dict, mais peut-être la solution suivante plus simple serait mieux: (. Peut-être la imbriquée boucle peut être comprimé une impressionnante en une ligne, mais cela fonctionne et est lisible)

>>> assoc_list = ((('parrot','spam','cheese_shop'), 'sketch'), (('Cleese', 'Gilliam', 'Palin'), 'actors')) 
>>> equiv_dict = dict() 
>>> for keys, value in assoc_list: 
    for key in keys: 
     equiv_dict[key] = value 


>>> equiv_dict['parrot'] 
'sketch' 
>>> equiv_dict['spam'] 
'sketch' 

+1

Pas pour les faibles de cœur: equiv_dict = dict (somme ([[(k, v) pour k dans ks] pour (ks, v) dans assoc_list], [])) –

0

Si vous voulez avoir plusieurs clés pointant vers la même valeur, à savoir

m_dictionary{('k1', 'k2', 'k3', 'k4'):1, ('k5', 'k6'):2} et les accès comme,

`print(m_dictionary['k1'])` ==> `1`. 

Vérifiez ce module python dictionnaire multilingue multi_key_dict. Installez et importez-le. https://pypi.python.org/pypi/multi_key_dict

Questions connexes