2012-04-17 42 views
5

Mam tabeli w postaci:Przetłumacz tabelę na słownik hierarchiczny?

A1, B1, C1, (value) 
A1, B1, C1, (value) 
A1, B1, C2, (value) 
A1, B2, C1, (value) 
A1, B2, C1, (value) 
A1, B2, C2, (value) 
A1, B2, C2, (value) 
A2, B1, C1, (value) 
A2, B1, C1, (value) 
A2, B1, C2, (value) 
A2, B1, C2, (value) 
A2, B2, C1, (value) 
A2, B2, C1, (value) 
A2, B2, C2, (value) 
A2, B2, C2, (value) 

chciałbym z nim pracować w Pythonie jak słownik, o postaci:

H = { 
    'A1':{ 
     'B1':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B2':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B3':{ 
      'C1':[],'C2':[],'C3':[] } 
    }, 
    'A2':{ 
     'B1':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B2':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B3':{ 
      'C1':[],'C2':[],'C3':[] } 
    } 
} 

Więc H[A][B][C] daje w wyniku konkretnego unikalną listę wartości. W przypadku małych słowników mogę z góry zdefiniować strukturę, ale szukam skutecznego sposobu na powtórzenie tabeli i zbudowanie słownika bez określania kluczy słownika z wyprzedzeniem.

+5

Czy zawsze szukasz potrójnych wartości A, B, C? Jeśli tak, lepiej będzie, jeśli użyjesz jednego "dyktatu", używając tych trzech trójek jako kluczy. –

Odpowiedz

8
input = [('A1', 'B1', 'C1', 'Value'), (...)] 

from collections import defaultdict 

tree = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) 
#Alternatively you could use partial() rather than lambda: 
#tree = defaultdict(partial(defaultdict, partial(defaultdict, list))) 

for x, y, z, value in input: 
    tree[x][y][z].append(value) 
+1

Zauważ, że jeśli tabela jest plikiem tekstowym, będziesz potrzebował czegoś takiego jak '' with open ("table") jako plik: '' '' input = [line.split() dla wiersza w pliku] ''. –

+2

Alternatywą do używania lambd jest użycie '' functools.partial() '': '' tree = defaultdict (partial (defaultdict, partial (defaultdict, list))) '' - ja to rozumiem, ale to może być po prostu bądź mną. –

+0

@ Battsware Ciekawe, dzięki za to. –

2
d = {} 
for (a, b, c, value) in your_table_of_tuples: 
    d.setdefault(a, {}).setdefault(b,{}).setdefault(c,[]).append(value) 
+0

Dlaczego warto użyć '' setdefault() '' over a 'defaultdict''? –

+0

@Lattyware: dlaczego nie? – vartec

+0

Powiedziałbym, że to dużo brzydsze, kiedy go używasz. –

4

Jeśli kiedykolwiek dostęp tylko H [A] [B] [C] (czyli nigdy H [A] oder H [A] [B] w spokoju), Chciałbym zaproponować IMO czystsze rozwiązanie: Użyj Tuples jako defaultdict Index:

from collections import defaultdict 
h = defaultdict(list) 
for a, b, c, value in input: 
    h[a, b, c].append(value) 
+0

To również bardzo ważne (i eleganckie) rozwiązanie, chociaż nie wymaga osobnego dostępu do subdictów. (edytowane w celu usunięcia dodatkowych wcięć, niepotrzebnych nawiasów i PEP-8 do oznaczania nazw zmiennych). –

+0

Dziękujemy za opublikowanie tego rozwiązania. W tym przypadku potrzebuję uzyskać dostęp do pod-słowników, ale nie określiłem tego w pytaniu. Będzie to niezwykle eleganckie, jeśli taki przypadek istnieje w przyszłości. –