2011-12-18 5 views
14

D'une autre fonction, j'ai des tuples comme ceci ('falseName', 'realName', positionOfMistake), par exemple. ('Milter', 'Miller', 4). Je dois écrire une fonction qui fait un dictionnaire comme celui-ci:dictionnaire python de dictionnaires

D={realName:{falseName:[positionOfMistake], falseName:[positionOfMistake]...}, 
    realName:{falseName:[positionOfMistake]...}...} 

La fonction doit prendre un dictionnaire et un tuple comme ci-dessus, comme arguments.

Je pensais quelque chose comme ça pour commencer:

def addToNameDictionary(d, tup): 
    dictionary={} 
    tup=previousFunction(string) 
    for element in tup: 
     if not dictionary.has_key(element[1]): 
      dictionary.append(element[1]) 
    elif: 
     if ... 

Mais il ne fonctionne pas et je suis un peu stucked ici.

+0

vous êtes la indentation est erroné. et qu'est-ce qui ne fonctionne pas exactement? – yurib

+2

Le 'tup' dans le paramètre est emporté par la ligne 'tup = previ ..'. Le code a l'air de ne pas tenir la grande image dans votre tête. Je pense arrêter, m'éloigner de l'ordinateur, respirer profondément, faire une promenade, m'asseoir, fermer les yeux et écrire le code avec un crayon et du papier. – matiu

Répondre

15

Si ce n'est d'ajouter une nouvelle ligne, et vous êtes sûr qu'il n'y a pas de collision dans le dictionnaire interne que vous pouvez faire ceci:

def addNameToDictionary(d, tup): 
    if tup[0] not in d: 
     d[tup[0]] = {} 
    d[tup[0]][tup[1]] = [tup[2]] 
+3

Le test has_key est mieux écrit 'si tup [0] pas dans d:' –

+0

d'accord - est-ce pour la perfomance? – aweis

+1

http://stackoverflow.com/questions/1323410/has-key-or-in –

10

L'utilisation collections.defaultdict est un grand gain de temps lorsque vous êtes construire des dits et ne pas savoir à l'avance quelles clés vous allez avoir.

Ici, il est utilisé deux fois: pour la dict qui en résulte, et pour chacune des valeurs dans le dict.

import collections 

def aggregate_names(errors): 
    result = collections.defaultdict(lambda: collections.defaultdict(list)) 
    for real_name, false_name, location in errors: 
     result[real_name][false_name].append(location) 
    return result 

En combinant ceci avec votre code:

dictionary = aggregate_names(previousFunction(string)) 

Ou à tester:

EXAMPLES = [ 
    ('Fred', 'Frad', 123), 
    ('Jim', 'Jam', 100), 
    ('Fred', 'Frod', 200), 
    ('Fred', 'Frad', 300)] 
print aggregate_names(EXAMPLES) 
8

de setdefault de dictionnaire est une bonne façon de mettre à jour une entrée dict existante si elle est là, ou créer un nouveau si ce n'est pas tout d'un coup:

Style de bouclage:

# This is our sample data 
data = [("Milter", "Miller", 4), ("Milter", "Miler", 4), ("Milter", "Malter", 2)] 

# dictionary we want for the result 
dictionary = {} 

# loop that makes it work 
for realName, falseName, position in data: 
    dictionary.setdefault(realName, {})[falseName] = position 

dictionnaire est maintenant égal à:

{'Milter': {'Malter': 2, 'Miler': 4, 'Miller': 4}} 
Questions connexes