2012-04-17 2 views
5

У меня есть таблица вида:Перевести таблицу в иерархический словарь?

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) 

Я хотел бы работать с ним в питоне в качестве словаря, форм:

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':[] } 
    } 
} 

Так что H[A][B][C] возвращающего особого уникального список значения. Для небольших словарей я мог бы заранее определить структуру заранее, как указано выше, но я ищу эффективный способ перебора по таблице и создания словаря, не указав заранее словарные ключи.

+5

Вы всегда ищете тройку значений A, B, C? Если это так, вам будет лучше с одним «dict», используя эти тройки в качестве ключей. –

ответ

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

Обратите внимание, что если таблица является текстовым файлом, вам нужно что-то вроде '' with open ("table") в качестве файла: '' '' input = [line.split() для строки в файле] ''. –

+2

Альтернативой использованию lambdas здесь является использование '' functools.partial() '': '' tree = defaultdict (partial (defaultdict, partial (defaultdict, list))) '' - Я нахожу это более ясным, но это может быть просто будь мной. –

+0

@Lattyware Интересно, спасибо за это. –

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

Зачем использовать '' setdefault() '' над '' defaultdict''? –

+0

@ Lattyware: почему бы и нет? – vartec

+0

Я бы сказал, что это намного уродливее, когда вы его используете. –

4

Если вы когда-либо доступ только к H [A] [B] [C] (то есть, никогда H [A] Одер H [A] [B] в одиночку), я бы предложил IMO: Использовать кортежи как defaultdict Индекс:

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

Это очень действительное (и изящное) решение, хотя оно требует, чтобы он не захотел получить доступ к субдиктограммам отдельно. (отредактировано, чтобы удалить некоторые дополнительные отступы, ненужные скобки и PEP-8именование имен переменных). –

+0

Спасибо за публикацию этого решения. В этом случае мне нужно получить доступ к суб-словарям, но я не указал это в вопросе. Это будет чрезвычайно элегантно, если это произойдет в будущем. –

Смежные вопросы