2016-11-05 2 views
3

Я новичок в Python и в настоящее время с помощью Python 2. Я построил многомерный словарь, который выглядит следующим образом:печати многомерный словарь с повторяющимся ключом

targets = {house: {N: {red: {A:1}, garden: {N: 6}}} 
      {great: {A: {very: {Adv:12}, so: {Adv: 5}, a: {Det: 3}}}} 
etc. 

В основном всегда есть 4 вложенные словари, но записи из «Третий» словарь ({red: {}, horse: {} и т. д.) может состоять из произвольного количества элементов. Таким образом, количество элементов в словаре меняется.

Теперь я хотел бы написать словарь в файл, желательно в csv-файл. Выходной файл должен отображать все записи в виде вкладок, каждая строка начинается с самой внешней клавиши. Например:

house N red  A 1 
house N garden N 6 
great A very  Adv 12 
great A so  Adv 5 
great A a  Det 3 

Я знаю, есть много сообщений о печати многомерных словарей, однако я не нашел один (пока), где первейшую ключ печатаются во время каждой итерации. Я попытался включить фрагменты кода, предоставленные для других вопросов, касающихся многомерных словарей, но пока это не сработало.

Я только успел написать словарь в обычный .txt-файл в формате словаря с этим цикл:

for target in targets_dict: 
    results.write(str(target) + str(targets_dict[str(target)]) + '\n') 

или записать его в CSV-файл с помощью csvwriter (я знаю, что есть также DictWriter, я просто не мог заставить его работать правильно):

w = csv.writer(results, delimiter = '\t') 
for target in targets_dict.iteritems(): 
    w.writerow(target) 

Очевидно, что это довольно простой и итерация не входит внутренние словари.

Попытка модифицированного решения, которое было отправлено в связанную с этим проблему (recursively traverse multidimensional dictionary, dimension unknown) всегда находится в ожидаемом символьном буфере-объекте.

for for k,v in sorted(targets_dict.items(),key=lambda x: x[0]): 
    if isinstance(v, dict): 
     results.write(" ") + ("%s %s") % (k, v) 

Каждое предложение или намек ценится, чтобы помочь мне понять логику всего этого, так что я могу понять это.

+1

Re. переменная 'target': это список dicts или все ключи в самых дальних словарях уникальны? – Eugene

+0

все ключи во внешнем словаре уникальны –

ответ

1

Это простое решение. Идея состоит в том, чтобы просто перебрать dict, в список, а затем создать файл tsv из этого списка, но только потому, что вы знаете глубину гнезда (4, что кажется ОК). Нижеследующее не оптимизировано для скорости и не проверяет существование где-либо, но, надеюсь, вы получите эту идею.

import csv 
targets = {'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 
      'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}}} 
with open('targets.tsv', 'w', newline='\n') as tsvfile: 
    writer = csv.writer(tsvfile, delimiter='\t') 
    for t in targets: 
     for u in targets[t]: 
      for v in targets[t][u]: 
       for w in targets[t][u][v]: 
        #print [t, u, v, w, targets[t][u][v][w]] 
        writer.writerow([t, u, v, w, targets[t][u][v][w]]) 

Печать:

['house', 'N', 'red', 'A', 1] 
['house', 'N', 'garden', 'N', 6] 
['great', 'A', 'very', 'Adv', 12] 
['great', 'A', 'so', 'Adv', 5] 
['great', 'A', 'a', 'Det', 3] 

А также создает файл TSV:

house N red A 1 
house N garden N 6 
great A very Adv 12 
great A so Adv 5 
great A a Det 3 

EDIT: обновленный код в соответствии комментарий в ОП (ключи в самом внешнем словаре уникальны и их следует рассматривать как ключи к targets).

+1

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

+0

Спасибо за ответ и выбор ответа, поэтому многие новые пользователи этого не делают, и это такие люди, как вы, которые восстанавливают мою готовность помочь тем, кто начинается с SO! Еще раз спасибо! – Eugene

+0

Обновлен код для отражения комментариев для завершения. – Eugene

1

Рекурсия действительно является решением проблемы. Вы можете определить функцию генератора, которая рекурсивно пересекает словарь при построении пути к обнаруженным элементам.Когда вы сталкиваетесь с неполучение Dict только yield что бы ни было добавлено в пути и написать, что в CSV-файл:

import csv 

targets = { 
    'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 
    'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}} 
} 

def get_rows(o, path=None): 
    if path is None: 
     path = [] 

    # Base case, add object to path and yield it 
    if not isinstance(o, dict): 
     path.append(o) 
     yield path 
     path.pop() 
     return 

    for k, v in o.items(): 
     path.append(k) 
     yield from get_rows(v, path) 
     path.pop() 

with open('result.csv', 'w', newline='') as f: 
    writer = csv.writer(f, delimiter='\t') 
    for row in get_rows(targets): 
     writer.writerow(row) 

Выход:

great A a Det 3 
great A so Adv 5 
great A very Adv 12 
house N red A 1 
house N garden N 6 

Обратите внимание, что на выходе вы получаете может быть в другом порядке поскольку dict неупорядочен. Вышеупомянутое решение будет работать с вложенными словарями с любой глубиной. Если вы используете Python 2, код нужно немного подкорректировать, так как Python 2 не имеет yield from.

+0

OP указывает: «Выходной файл должен отображать все записи в виде вкладок», необходимо установить разделитель табуляции в приведенном выше коде. – Eugene

+0

@ Юджин Хорошая точка, исправлено это. – niemmi

+0

@niemmi Большое вам спасибо, я использую Python 2 для этого проекта, но я попробовал его с python 3, и он дает желаемый результат, который, конечно же, прекрасен;) –

1

Это очень просто только гнездо для петель по всем dicts:

import csv 

targets = {'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}}} 

with open('file.csv', 'wb') as csvfile: 
    csvwriter = csv.writer(csvfile, delimiter='\t') 
    for k,v in targets.iteritems(): 
    for k2,v2 in v.iteritems(): 
     for k3,v3 in v2.iteritems(): 
     for k4,v4 in v3.iteritems(): 
      csvwriter.writerow([str(k), str(k2), str(k3), str(k4), str(v4)]) 
      #print(str(k) + "\t" + str(k2) + "\t" + str(k3) + "\t" + str(k4) + "\t" + str(v4)) 

выходы именно то, что вы хотите.

+0

Большое вам спасибо за помощь, код делает именно что я искал. Я очень ценю ваш вклад, это очень помогло! –

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