Преобразование списка списков в словарь словарей в Python - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь преобразовать структуру данных списка списков в словарь словарей.

Список определен следующим образом:

l = [
  ['PP','Ear-rings', 'Holesovice', 2000],
  ['PP','Skirts', 'Holesovice', 1000],
  ['PP','Dresses', 'E-shop', 1500],
  ['BM','Butterfly', 'Holesovice', 1600]
]

Моя цель состоит в том, чтобы структура словаря была следующей:

#{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts' : 1000},
#         'E-shop' : {'Dresses' : 1500}},
# 'BM' : {'Holesovice' : {'Butterfly' : 1600}}
#}

Этот бит кода не возвращает желаемый результат:

labels_d = {}
items_d = {}
shops_d = {}

for index, row in enumerate(l):
  items_d[row[1]] = row[3]
  shops_d[row[2]] = items_d
  labels_d[row[0]] = shops_d

print(labels_d)

Я нашел несколько постов, которые касаются преобразования списков в словари здесь и здесь , но я не сделал так, как я хочу. Есть ли какой-нибудь «чистый» способ достижения структуры, описанной выше?

Ответы [ 5 ]

0 голосов
/ 07 сентября 2018

Здесь выложите довольно простой способ составить новый словарь:

Если элементы в каждой строке списка не соответствуют глубине словаря, просто добавьте / добавьте пару ключ-значение к диктовке.

Код:

list = [
    ['PP','Ear-rings', 'Holesovice', 2000],
    ['PP','Skirts', 'Holesovice', 1000],
    ['PP','Dresses', 'E-shop', 1500],
    ['BM','Butterfly', 'Holesovice', 1600]
]

dicta = {}
for row in list:
    if row[0] not in dicta.keys():
        dicta[row[0]] = {row[2]:{row[1]:row[3]}}
        continue
    if row[2] not in dicta[row[0]].keys():
        dicta[row[0]][row[2]] = {row[1]:row[3]}
        continue
    if row[1] not in dicta[row[0]][row[2]].keys():
        dicta[row[0]][row[2]][row[1]] = row[3]

print(dicta)

Выход:

{'BM': {'Holesovice': {'Butterfly': 1600}},
 'PP': {'E-shop': {'Dresses': 1500},
        'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}
0 голосов
/ 05 сентября 2018
def toNested1(l):
    def addKeyDict(map,key):    
        if key not in map:
            item = map[key] = {}
            return item            
        return map[key]

    zz = {}
    for a0,a1,a2,a3 in l :
        addKeyDict( addKeyDict( zz, a0) , a2 )[a1] = a3
    return zz
0 голосов
/ 05 сентября 2018

Вы можете использовать collections.defaultdict и повторять. В этом случае вы можете точно определить вложенный словарь, отражающий структуру данных.

from collections import defaultdict

L = [['PP','Ear-rings', 'Holesovice', 2000],
     ['PP','Skirts', 'Holesovice', 1000],
     ['PP','Dresses', 'E-shop', 1500],
     ['BM','Butterfly', 'Holesovice', 1600]]

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))

for code, item, shop, value in L:
    d[code][shop][item] = value

Результат

defaultdict({'BM': defaultdict({'Holesovice': defaultdict(int, {'Butterfly': 1600})}),
             'PP': defaultdict({'E-shop': defaultdict(int, {'Dresses': 1500}),
                                'Holesovice': defaultdict(int,
                                {'Ear-rings': 2000, 'Skirts': 1000})})})
0 голосов
/ 05 сентября 2018

Использование dict.setdefault(key, {}) - хороший способ приблизиться к созданию вложенных словарей фиксированной глубины.

l = [
  ['PP','Ear-rings', 'Holesovice', 2000],
  ['PP','Skirts', 'Holesovice', 1000],
  ['PP','Dresses', 'E-shop', 1500],
  ['BM','Butterfly', 'Holesovice', 1600]
]

d = {}

for tag, item, source, qty in l:
    d.setdefault(tag, {}).setdefault(source, {})[item] = qty 

выход

{'BM': {'Holesovice': {'Butterfly': 1600}},
 'PP': {'E-shop': {'Dresses': 1500},
        'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}

1010 * обобщение * Приведенное выше решение можно сделать более общим, создав класс вложенного словаря, отбросив требования, чтобы иметь фиксированную глубину. class NestedDict(dict): def __getitem__(self, item): if item not in self: self[item] = NestedDict() return super().__getitem__(item) d = NestedDict() for tag, item, source, qty in l: d[tag][source][item] = qty Также обратите внимание, что классовый подход создан, поэтому он создает объект, только если ключ не существует, в то время как setdefault подход создает пустой dict при каждом доступе.

0 голосов
/ 05 сентября 2018

Вы можете использовать бесконечно вложенный трюк defaultdict:

from collections import defaultdict

def nested_dict():
    return defaultdict(nested_dict)

nd = nested_dict()
for a, b, c, d in l:
    nd[a][c][b] = d
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...