2013-07-04 17 views
8

Ho una lista come indicato di seguito -Python Generare un dizionario dinamico dall'elenco delle chiavi

keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"] 
value1 = "Roger" 

Come si genera dizionario dinamica che può essere recuperato, come di seguito -

mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value 

Il la lista potrebbe essere qualsiasi cosa; Lunghezza variabile o costituiti da numero "N" di elementi sconosciuti a me ...

Ora io ho un altro elenco, in modo che il mio dizionario dovrebbe essere aggiornato di conseguenza

keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"] 
value2 = 25 

cioè se le chiavi "Persona", "Maschio", "ragazzo", "studente", "id_123" esiste già, la nuova chiave "età" dovrebbe essere aggiunto ...

+0

vorrei suggerire di aggiungere tutti gli elementi della lista e utilizzare la stringa risultante come chiave. Sarebbe molto più facile. – rajpy

+0

Le risposte a questa domanda possono aiutare: http://stackoverflow.com/questions/16384174/more-pythonic-way-of-counting-things-in-a-heavily-nested-defaultdict – dg123

risposta

8

sto solo imparando python, quindi il mio codice potrebbe essere non molto divinatorio, ma ecco il mio codice

d = {} 

keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"] 
keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"] 
value1 = "Roger" 
value2 = 3 

def insert(cur, list, value): 
    if len(list) == 1: 
     cur[list[0]] = value 
     return 
    if not cur.has_key(list[0]): 
     cur[list[0]] = {} 
    insert(cur[list[0]], list[1:], value) 

insert(d, keyList1, value1) 
insert(d, keyList2, value2) 

{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Age': 3, 'Name': 'Roger'}}}}}} 
+0

Questo finisce per essere abbastanza simile alla mia soluzione. Un semplice suggerimento: evitare '.has_key' quando possibile; preferisco il più veloce e più comprensibile 'if list [0] not in cur'. – nneonneo

+0

grazie, sono d'accordo che è più leggibile e conta la leggibilità, ma perché è più veloce? –

+1

Provalo usando 'timeit'. Sul mio computer, 'in' è due volte più veloce di' .has_key' (0.0672μs contro 0.117μs). '.has_key' è una ricerca di metodo, mentre' in' è un builtin che viene inviato molto più rapidamente. – nneonneo

-2
>>> mydict = {} 
>>> keyList1 = ["Person", "Male", "Boy", "Student", "id_123", "Name"] 
>>> value1 = "Roger" 
>>> reduce(lambda x, y: x.setdefault(y, {}), keyList1, mydict) 
{} 
>>> mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] = value1 

si può anche farlo in un passo come questo

>>> keyList2 = ["Person", "Male", "Boy", "Student", "id_123", "Age"] 
>>> value2 = 25 
>>> reduce(lambda x,y: x.setdefault(y,{}), keyList2[:-1], mydict).update({keyList2[-1]: value2}) 
+0

>>> mydict {' Persona ': {' Maschio ': {' Ragazzo ': {' Studente ': {' id_123 ': {' Nome ':' Roger '}}}}}} –

+0

@AbhishekKulkarni, er .. dove si trova 'reduce (lambda x, y: x.setdefault (y, {}), keyList1, mydict) 'dipende dal numero di elementi o dalle chiavi specifiche? –

1

Crea la tua classe derivata da dict in cui il metodo init prende una lista e un singolo valore come input e iterare attraverso l'elenco impostando le chiavi da valutare, definire un metodo di aggiornamento che richiede un elenco e un nuovo valore e per ogni elemento che non è già una chiave, impostarlo sul nuovo valore (assumendo che sia ciò di cui si ha bisogno) .

dimenticare l'idea di

mydict [ "persona"] [ "maschio"] [ "ragazzo"] [ "Student"] [ "id_123"] [ "Nome"] = valore1

quanto confonde con sottoindici.

4

È possibile farlo facendo nidificati defaultdict s:

from collections import defaultdict 

def recursive_defaultdict(): 
    return defaultdict(recursive_defaultdict) 

def setpath(d, p, k): 
    if len(p) == 1: 
     d[p[0]] = k 
    else: 
     setpath(d[p[0]], p[1:], k) 

mydict = recursive_defaultdict() 

setpath(mydict, ["Person", "Male", "Boy", "Student", "id_123", "Name"], 'Roger') 

print mydict["Person"]["Male"]["Boy"]["Student"]["id_123"]["Name"] 
# prints 'Roger' 

Questo ha il bel vantaggio di essere in grado di scrivere

mydict['a']['b'] = 4 

senza necessariamente dover utilizzare il setpath aiutante.

È possibile farlo senza ricorsivo defaultdict troppo:

def setpath(d, p, k): 
    if len(p) == 1: 
     d[p[0]] = k 
    else: 
     setpath(d.setdefault(p[0], {}), p[1:], k) 
0

che sto cercando di fare con roba simile, quindi posso suggerire alcune linee guida, ma ancora una volta io sono ingenuo in Python, quindi questo è solo un orientamento...

avete una lista di chiavi , quindi si può sicuramente iniziare con un ciclo iterare per ogni valore e quindi assegnare il valore

come

for i in keylist: 
if type(keylist[i]) == dict: 
     do something 
    else: 
     keylist[i] = {} 

nel fare qualcosa, è necessario incrementare io e cambio indice a [i] [i + 1] e poi seguo lo stesso fino a + n = len (keylist)

0

Utilizzare tuple(keyList1) come chiave. (le tuple sono immutabili e quindi possono essere dettate dalle chiavi).

Avrete un mondo di mal di testa con l'approccio di dict annidato. (cicli nidificati per l'enumerazione, dati legacy quando la gerarchia deve cambiare, ecc.).

Su un secondo pensiero, forse si dovrebbe definire una classe persona

class Person(object): 
    gender = "Male" 
    group = "Student" 
    id = 123 
    Name = "John Doe" 

quindi utilizzare un elenco di tutte le persone e filtro con per esempio

male_students = [s for s in ALL_PERSONS where s.gender=="Male" and s.group="Student"] 

... per < = 10000 studenti si dovrebbe essere performancewise fini.

3

Forse si potrebbe creare una sottoclasse dict:

class ChainDict(dict): 
    def set_key_chain(self, keyList, value): 
     t = self 
     for k in keyList[:-1]: 
      t = t.setdefault(k, {}) 
     t.setdefault(keyList[-1], value) 

c = ChainDict() 
c.set_key_chain(['Person', 'Male', 'Boy', 'Student', 'id_123', 'Name'], 'Roger') 
print c 
>>{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Name': 'Roger'}}}}}} 

c.set_key_chain(['Person', 'Male', 'Boy', 'Student', 'id_123', 'Age'], 25) 
print c 
>>{'Person': {'Male': {'Boy': {'Student': {'id_123': {'Age': 25, 
     'Name': 'Roger'}}}}}} 
Problemi correlati