1

I take some lists from my database:

print(liste)
[('VEST', 'MODEL-1', 'BEIGE', 'M'), 
 ('VEST', 'MODEL-1', 'BEIGE', 'S'), 
 ('JACKET', 'MOD-1', 'GREEN', 'S'), 
 ('JACKET', 'MOD-1', 'GREEN', 'M'), 
 ('JACKET', 'MOD-2', 'BLACK', 'L'), 
 ('JACKET', 'MOD-2', 'BLACK', 'XL')]

now I need to create a dict like this:

mydict = {'VEST' : {'MODEL-1' : {'BEIGE' : ('S', 'M')}},
          'JACKET' : ({'MOD-1' : {'GREEN' : ('S', 'M')}},
                      {'MOD-2' : {'BLACK' : ('L', 'XL')}})}

I will use this in tkinter like json. I need to choose something like that:

print(mydict['JACKET'][1]['MOD-2']['BLACK'][0])
L
# Or
print(mydict['VEST']['MODEL-1']['BEIGE'][0])
S

How can I create a dict? I'm tired of trying different ways. I will be very happy if I can get good advice

scan
  • 107
  • 10
  • Why does `'JACKET'` maps on a tuple? And aren't these two keys stored in the *same* dictionary? – Willem Van Onsem Jun 13 '17 at 21:37
  • Because i have difficult products in same categories. But i must chose first categories, (Jacket or Pants) after must chose model, color, size (Jacket: Model 1: Color Beige: Size XL) Can be same Categories but Difficult model or color. – scan Jun 13 '17 at 22:02

2 Answers2

4

What you are showing is not very consistent, but I think you may benefit from using a collections.defaultdict:

In [1]: from collections import defaultdict

In [2]: liste = [('VEST', 'MODEL-1', 'BEIGE', 'M'), 
   ...:  ('VEST', 'MODEL-1', 'BEIGE', 'S'), 
   ...:  ('JACKET', 'MOD-1', 'GREEN', 'S'), 
   ...:  ('JACKET', 'MOD-1', 'GREEN', 'M'), 
   ...:  ('JACKET', 'MOD-2', 'BLACK', 'L'), 
   ...:  ('JACKET', 'MOD-2', 'BLACK', 'XL')]

In [3]: mydict = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))

In [4]: for kind, model, color, size in liste:
   ...:     mydict[kind][model][color].append(size)
   ...:     

In [5]: mydict['VEST']['MODEL-1']['BEIGE']
Out[5]: ['M', 'S']

The defaultdict constructor takes a "factory" function as argument, i.e. a callable which is called without parameters to substitute a missing value. For example, defaultdict(list) will have an empty list for every missing key when you try to access it.

In this case I created a nested defaultdict object, which creates another defaultdict for every key. The inner one also creates a defaultdict, which also uses defaultdict as factory. This reflects your data hierarchy and saves you multiple checks or exception handling for missing keys.

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
0

You could try a defaultdict as demonstrated by @LevLevitsky, or you could try this workable, albeit convoluted way:

result = {}
for i in liste:
    if i[0] not in result.keys():
            result[i[0]] = {i[1]: {i[2]: tuple(i[3:4])}}
    else:
            if i[1] not in result[i[0]].keys():
                   result[i[0]][i[1]] = {i[2]: tuple(i[3:4])}
            else:
                   if i[2] not in result[i[0]][i[1]].keys():
                            result[i[0]][i[1]][i[2]] = tuple(i[3:4])
                   else:
                            result[i[0]][i[1]][i[2]]+=tuple(i[3:4])

print result #{'JACKET': {'MOD-2': {'BLACK': ('L', 'XL')}, 'MOD-1': {'GREEN': ('S', 'M')}}, 'VEST': {'MODEL-1': {'BEIGE': ('M', 'S')}}}
A.J. Uppal
  • 19,117
  • 6
  • 45
  • 76
  • 1
    When checking for presence in dict, [there is no need to call `.keys()`](https://stackoverflow.com/q/1602934/1258041). On Python 2 this may be significantly slower (not sure about Python 3). – Lev Levitsky Jun 13 '17 at 22:12
  • Yes, calling `.keys` when checking for keys I is an antipattern. But in this instance you don't have to check the keys anyway. Use `.setdefault` if you want to stick to a plain `dict` – juanpa.arrivillaga Jun 13 '17 at 23:00
  • A long but understandable recipe for novices like myself. Thank you so much – scan Jun 14 '17 at 05:13
  • @scan no problem, glad to be of help :) – A.J. Uppal Jun 14 '17 at 16:51