2010-03-05 6 views
27

J'utilise actuellement la méthode ci-dessous pour définir un dictionnaire multidimensionnel en python. Ma question est la suivante: est-ce la façon préférée de définir les dicts multidimensionnels?Meilleure façon de définir des dictionnaires multidimensionnels en python?

from collections import defaultdict 

def site_struct(): 
    return defaultdict(board_struct) 

def board_struct(): 
    return defaultdict(user_struct) 

def user_struct(): 
    return dict(pageviews=0,username='',comments=0) 

userdict = defaultdict(site_struct) 

pour obtenir la structure suivante:

userdict['site1']['board1']['username'] = 'tommy' 

J'utilise également ce pour incrémenter des compteurs à la volée pour un utilisateur sans avoir à vérifier si une clé existe ou est réglé sur 0 déjà. E.g .:

userdict['site1']['board1']['username']['pageviews'] += 1 
+0

ce code n'exécutera pas l'interpréteur in python. cela rend difficile de comprendre ce que vous essayez de faire. – krumpelstiltskin

Répondre

43

Les tuples sont lavables. Probablement je manque le point, mais pourquoi n'utilisez-vous pas un dictionnaire standard avec la convention que les clés seront triples? Par exemple:

userdict = {} 
userdict[('site1', 'board1', 'username')] = 'tommy' 
+1

Je recommande cette approche, sauf si vous devez passer userdict ['site1'] à une fonction quelconque. –

+0

J'aime cette idée. C'est exactement ce que les tuples sont bons en raison de leur nature immuable. – jathanism

+2

Cela fonctionne très bien, tant que vous n'avez pas besoin de lister toutes les entrées du forum sous 'site1'. –

1

Ceci est une question assez subjective de mon point de vue. Pour moi, la vraie question serait à quel moment faites-vous la promotion de cette structure de données imbriquée à des objets avec des méthodes pour vous isoler des changements. Cependant, j'ai connu pour créer de grands espaces de noms de prototypage avec les éléments suivants:

from collections import defaultdict 

def nesteddict(): 
    return defaultdict(nesteddict) 
+0

Cette solution conserve la possibilité d'itérer sur les dimensions, mais crée une dépendance pour nesteddict. – GregB

16

Vous pouvez créer un dictionnaire multidimensionnel de tout type comme celui-ci:

from collections import defaultdict 
from collections import Counter 

def multi_dimensions(n, type): 
    """ Creates an n-dimension dictionary where the n-th dimension is of type 'type' 
    """ 
    if n<=1: 
    return type() 
    return defaultdict(lambda:multi_dimensions(n-1, type)) 

>>> m = multi_dimensions(5, Counter) 
>>> m['d1']['d2']['d3']['d4'] 
Counter() 
+0

Quand j'essaye cela, j'obtiens 'TypeError: Required argument 'name' (pos 1) not found' qui fait référence à la ligne' return type() '. – hepcat72

+0

J'ai compris mon problème - c'est juste une différence entre la façon dont je définis les dictionnaires "N-Dimensional" et comment elle est définie ci-dessus. Par exemple. une donnée unique est indexée par 0 dimensions. Un tableau simple est indexé par 1 dim. Les vals dans un tableau de tableaux sont indexés par 2 dims. Et les dicts ne sont que des tableaux indexés par des chaînes. Les vals qu'il contient ne sont pas (pour moi) une dimension supplémentaire, même si je vois comment vous pourriez penser de cette façon. Dans l'exemple ci-dessus, je l'aurais appelé un 4D dict, pas 5. Donc mon code ne fonctionnait pas parce que je m'attendais à ce que le type au lieu d'une dimension dict @ 1 timide de ce qu'il m'a donné. – hepcat72

1

Ceci est très subjectif - mais si votre Dict devient de plus de 2-n de profondeur, je reviendrai à créer une classe et définir des méthodes/propriétés pour faire ce que vous voulez.

Je pense que votre objectif final serait de créer une structure de données "multi-colonnes" afin que vous puissiez stocker n'importe quel nombre d'attributs pour un objet particulier (dans ce cas, un site). Créer une classe de site permettrait d'accomplir cela et ensuite vous pouvez coller des instances où vous voulez n'importe quel autre objet (variable) - avec quelques exceptions notées.

Questions connexes