Converting list of lists into a dictionary of dictionaries in Python

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
19
down vote

favorite
1












I am trying to convert a list of lists data structure to a dictionary of dictionaries.



The list is defined as follows:



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


My aim is to have the dictionary structure as follows:



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


This bit of code does not return desired output:



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)


I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?










share|improve this question























  • If you found some posts then surely you must have tried something, even if it broke?
    – Mad Physicist
    Sep 5 at 13:58











  • stackoverflow.com/q/43234439/2988730
    – Mad Physicist
    Sep 5 at 14:08














up vote
19
down vote

favorite
1












I am trying to convert a list of lists data structure to a dictionary of dictionaries.



The list is defined as follows:



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


My aim is to have the dictionary structure as follows:



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


This bit of code does not return desired output:



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)


I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?










share|improve this question























  • If you found some posts then surely you must have tried something, even if it broke?
    – Mad Physicist
    Sep 5 at 13:58











  • stackoverflow.com/q/43234439/2988730
    – Mad Physicist
    Sep 5 at 14:08












up vote
19
down vote

favorite
1









up vote
19
down vote

favorite
1






1





I am trying to convert a list of lists data structure to a dictionary of dictionaries.



The list is defined as follows:



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


My aim is to have the dictionary structure as follows:



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


This bit of code does not return desired output:



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)


I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?










share|improve this question















I am trying to convert a list of lists data structure to a dictionary of dictionaries.



The list is defined as follows:



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


My aim is to have the dictionary structure as follows:



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


This bit of code does not return desired output:



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)


I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?







python python-3.x list dictionary nested






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 5 at 17:50









jpp

66.7k173983




66.7k173983










asked Sep 5 at 13:55









New2Python

17011




17011











  • If you found some posts then surely you must have tried something, even if it broke?
    – Mad Physicist
    Sep 5 at 13:58











  • stackoverflow.com/q/43234439/2988730
    – Mad Physicist
    Sep 5 at 14:08
















  • If you found some posts then surely you must have tried something, even if it broke?
    – Mad Physicist
    Sep 5 at 13:58











  • stackoverflow.com/q/43234439/2988730
    – Mad Physicist
    Sep 5 at 14:08















If you found some posts then surely you must have tried something, even if it broke?
– Mad Physicist
Sep 5 at 13:58





If you found some posts then surely you must have tried something, even if it broke?
– Mad Physicist
Sep 5 at 13:58













stackoverflow.com/q/43234439/2988730
– Mad Physicist
Sep 5 at 14:08




stackoverflow.com/q/43234439/2988730
– Mad Physicist
Sep 5 at 14:08












5 Answers
5






active

oldest

votes

















up vote
24
down vote



accepted










Using dict.setdefault(key, ) is a good way to approach the creation of nested dictionaries of fixed depth.



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


Output



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


Generalization



The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.



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


Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.






share|improve this answer


















  • 4




    It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
    – Mad Physicist
    Sep 5 at 14:09










  • @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
    – Patrick Haugh
    Sep 5 at 14:47






  • 1




    @MadPhysicist this is solved in the general approach
    – Olivier Melançon
    Sep 5 at 15:47






  • 1




    I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
    – Mad Physicist
    Sep 5 at 18:47






  • 1




    I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
    – Mad Physicist
    Sep 6 at 2:08

















up vote
17
down vote













You can use the infinitely nested defaultdict trick:



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





share|improve this answer






















  • I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
    – Olivier Melançon
    Sep 5 at 14:14






  • 1




    @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
    – schwobaseggl
    Sep 5 at 14:25







  • 1




    @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
    – Olivier Melançon
    Sep 5 at 14:29











  • @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
    – schwobaseggl
    Sep 5 at 14:35






  • 1




    This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
    – jpp
    Sep 5 at 16:10


















up vote
6
down vote













You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.



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


Result



defaultdict('BM': defaultdict('Holesovice': defaultdict(int, 'Butterfly': 1600)),
'PP': defaultdict('E-shop': defaultdict(int, 'Dresses': 1500),
'Holesovice': defaultdict(int,
'Ear-rings': 2000, 'Skirts': 1000)))





share|improve this answer




















  • It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
    – Olivier Melançon
    Sep 5 at 17:39

















up vote
0
down vote













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





share|improve this answer



























    up vote
    0
    down vote













    Here post a pretty straightforward way to compose a new dictionary:



    If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.



    code:



    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)


    output:



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





    share|improve this answer




















      Your Answer





      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52186918%2fconverting-list-of-lists-into-a-dictionary-of-dictionaries-in-python%23new-answer', 'question_page');

      );

      Post as a guest






























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      24
      down vote



      accepted










      Using dict.setdefault(key, ) is a good way to approach the creation of nested dictionaries of fixed depth.



      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


      Output



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


      Generalization



      The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.



      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


      Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.






      share|improve this answer


















      • 4




        It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
        – Mad Physicist
        Sep 5 at 14:09










      • @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
        – Patrick Haugh
        Sep 5 at 14:47






      • 1




        @MadPhysicist this is solved in the general approach
        – Olivier Melançon
        Sep 5 at 15:47






      • 1




        I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
        – Mad Physicist
        Sep 5 at 18:47






      • 1




        I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
        – Mad Physicist
        Sep 6 at 2:08














      up vote
      24
      down vote



      accepted










      Using dict.setdefault(key, ) is a good way to approach the creation of nested dictionaries of fixed depth.



      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


      Output



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


      Generalization



      The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.



      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


      Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.






      share|improve this answer


















      • 4




        It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
        – Mad Physicist
        Sep 5 at 14:09










      • @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
        – Patrick Haugh
        Sep 5 at 14:47






      • 1




        @MadPhysicist this is solved in the general approach
        – Olivier Melançon
        Sep 5 at 15:47






      • 1




        I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
        – Mad Physicist
        Sep 5 at 18:47






      • 1




        I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
        – Mad Physicist
        Sep 6 at 2:08












      up vote
      24
      down vote



      accepted







      up vote
      24
      down vote



      accepted






      Using dict.setdefault(key, ) is a good way to approach the creation of nested dictionaries of fixed depth.



      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


      Output



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


      Generalization



      The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.



      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


      Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.






      share|improve this answer














      Using dict.setdefault(key, ) is a good way to approach the creation of nested dictionaries of fixed depth.



      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


      Output



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


      Generalization



      The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.



      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


      Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Sep 8 at 13:38

























      answered Sep 5 at 14:01









      Olivier Melançon

      11.8k11436




      11.8k11436







      • 4




        It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
        – Mad Physicist
        Sep 5 at 14:09










      • @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
        – Patrick Haugh
        Sep 5 at 14:47






      • 1




        @MadPhysicist this is solved in the general approach
        – Olivier Melançon
        Sep 5 at 15:47






      • 1




        I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
        – Mad Physicist
        Sep 5 at 18:47






      • 1




        I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
        – Mad Physicist
        Sep 6 at 2:08












      • 4




        It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
        – Mad Physicist
        Sep 5 at 14:09










      • @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
        – Patrick Haugh
        Sep 5 at 14:47






      • 1




        @MadPhysicist this is solved in the general approach
        – Olivier Melançon
        Sep 5 at 15:47






      • 1




        I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
        – Mad Physicist
        Sep 5 at 18:47






      • 1




        I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
        – Mad Physicist
        Sep 6 at 2:08







      4




      4




      It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
      – Mad Physicist
      Sep 5 at 14:09




      It really grinds something in the back of my head to see a new object created every time you call setdefault, although this is a very nice solution.
      – Mad Physicist
      Sep 5 at 14:09












      @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
      – Patrick Haugh
      Sep 5 at 14:47




      @OlivierMelançon They just mean that NestedDict() is called whether or not item already has a value, which is a little inelegant.
      – Patrick Haugh
      Sep 5 at 14:47




      1




      1




      @MadPhysicist this is solved in the general approach
      – Olivier Melançon
      Sep 5 at 15:47




      @MadPhysicist this is solved in the general approach
      – Olivier Melançon
      Sep 5 at 15:47




      1




      1




      I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
      – Mad Physicist
      Sep 5 at 18:47




      I'm aware of the solution and I'm sure you are too. I liked your original answer for it's simplicity. My comment was just a general dissatisfaction with setdefault. It would be nice to have another method that accepts a callable instead of a preconstructed instance.
      – Mad Physicist
      Sep 5 at 18:47




      1




      1




      I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
      – Mad Physicist
      Sep 6 at 2:08




      I've never posted anything on the Python discussion thread before. Maybe now would be a good time to start. I'll see if I can come up with a simple implementation first.
      – Mad Physicist
      Sep 6 at 2:08












      up vote
      17
      down vote













      You can use the infinitely nested defaultdict trick:



      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





      share|improve this answer






















      • I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
        – Olivier Melançon
        Sep 5 at 14:14






      • 1




        @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
        – schwobaseggl
        Sep 5 at 14:25







      • 1




        @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
        – Olivier Melançon
        Sep 5 at 14:29











      • @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
        – schwobaseggl
        Sep 5 at 14:35






      • 1




        This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
        – jpp
        Sep 5 at 16:10















      up vote
      17
      down vote













      You can use the infinitely nested defaultdict trick:



      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





      share|improve this answer






















      • I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
        – Olivier Melançon
        Sep 5 at 14:14






      • 1




        @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
        – schwobaseggl
        Sep 5 at 14:25







      • 1




        @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
        – Olivier Melançon
        Sep 5 at 14:29











      • @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
        – schwobaseggl
        Sep 5 at 14:35






      • 1




        This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
        – jpp
        Sep 5 at 16:10













      up vote
      17
      down vote










      up vote
      17
      down vote









      You can use the infinitely nested defaultdict trick:



      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





      share|improve this answer














      You can use the infinitely nested defaultdict trick:



      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






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Sep 5 at 14:22

























      answered Sep 5 at 14:00









      schwobaseggl

      31k31835




      31k31835











      • I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
        – Olivier Melançon
        Sep 5 at 14:14






      • 1




        @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
        – schwobaseggl
        Sep 5 at 14:25







      • 1




        @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
        – Olivier Melançon
        Sep 5 at 14:29











      • @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
        – schwobaseggl
        Sep 5 at 14:35






      • 1




        This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
        – jpp
        Sep 5 at 16:10

















      • I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
        – Olivier Melançon
        Sep 5 at 14:14






      • 1




        @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
        – schwobaseggl
        Sep 5 at 14:25







      • 1




        @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
        – Olivier Melançon
        Sep 5 at 14:29











      • @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
        – schwobaseggl
        Sep 5 at 14:35






      • 1




        This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
        – jpp
        Sep 5 at 16:10
















      I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
      – Olivier Melançon
      Sep 5 at 14:14




      I love this as well. I feel it would be somewhat neater if you made nested_dict a class instead of a factory.
      – Olivier Melançon
      Sep 5 at 14:14




      1




      1




      @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
      – schwobaseggl
      Sep 5 at 14:25





      @OlivierMelançon Certainly a challenge to have the recursive logic in a class in such a tidy way. After all, the argument to the defaultdict constructor is the default factory ;-)
      – schwobaseggl
      Sep 5 at 14:25





      1




      1




      @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
      – Olivier Melançon
      Sep 5 at 14:29





      @schwobaseggl it's fairly simple really since the factory is stored as an instance argument. class NestedDict(defaultdict): def __init__(self): self.default_factory = NestedDict
      – Olivier Melançon
      Sep 5 at 14:29













      @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
      – schwobaseggl
      Sep 5 at 14:35




      @OlivierMelançon True, I like that as well. It certainly provides an additional insight.
      – schwobaseggl
      Sep 5 at 14:35




      1




      1




      This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
      – jpp
      Sep 5 at 16:10





      This answer is, of course, good. BUT I do think it's important to note the difference between this and my very similar but more precise answer. When you check a key nd['key1']['key2']['key3'] and it doesn't exist you will get an empty dictionary , while in my solution you get 0. It may be relevant as conceptually you may not expect .
      – jpp
      Sep 5 at 16:10











      up vote
      6
      down vote













      You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.



      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


      Result



      defaultdict('BM': defaultdict('Holesovice': defaultdict(int, 'Butterfly': 1600)),
      'PP': defaultdict('E-shop': defaultdict(int, 'Dresses': 1500),
      'Holesovice': defaultdict(int,
      'Ear-rings': 2000, 'Skirts': 1000)))





      share|improve this answer




















      • It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
        – Olivier Melançon
        Sep 5 at 17:39














      up vote
      6
      down vote













      You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.



      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


      Result



      defaultdict('BM': defaultdict('Holesovice': defaultdict(int, 'Butterfly': 1600)),
      'PP': defaultdict('E-shop': defaultdict(int, 'Dresses': 1500),
      'Holesovice': defaultdict(int,
      'Ear-rings': 2000, 'Skirts': 1000)))





      share|improve this answer




















      • It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
        – Olivier Melançon
        Sep 5 at 17:39












      up vote
      6
      down vote










      up vote
      6
      down vote









      You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.



      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


      Result



      defaultdict('BM': defaultdict('Holesovice': defaultdict(int, 'Butterfly': 1600)),
      'PP': defaultdict('E-shop': defaultdict(int, 'Dresses': 1500),
      'Holesovice': defaultdict(int,
      'Ear-rings': 2000, 'Skirts': 1000)))





      share|improve this answer












      You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.



      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


      Result



      defaultdict('BM': defaultdict('Holesovice': defaultdict(int, 'Butterfly': 1600)),
      'PP': defaultdict('E-shop': defaultdict(int, 'Dresses': 1500),
      'Holesovice': defaultdict(int,
      'Ear-rings': 2000, 'Skirts': 1000)))






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Sep 5 at 14:01









      jpp

      66.7k173983




      66.7k173983











      • It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
        – Olivier Melançon
        Sep 5 at 17:39
















      • It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
        – Olivier Melançon
        Sep 5 at 17:39















      It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
      – Olivier Melançon
      Sep 5 at 17:39




      It took me a while to notice it, but returning 0 at the bottom of the dict is both subtle and neat
      – Olivier Melançon
      Sep 5 at 17:39










      up vote
      0
      down vote













      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





      share|improve this answer
























        up vote
        0
        down vote













        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





        share|improve this answer






















          up vote
          0
          down vote










          up vote
          0
          down vote









          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





          share|improve this answer












          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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 5 at 15:17









          napuzba

          3,21231021




          3,21231021




















              up vote
              0
              down vote













              Here post a pretty straightforward way to compose a new dictionary:



              If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.



              code:



              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)


              output:



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





              share|improve this answer
























                up vote
                0
                down vote













                Here post a pretty straightforward way to compose a new dictionary:



                If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.



                code:



                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)


                output:



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





                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  Here post a pretty straightforward way to compose a new dictionary:



                  If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.



                  code:



                  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)


                  output:



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





                  share|improve this answer












                  Here post a pretty straightforward way to compose a new dictionary:



                  If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.



                  code:



                  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)


                  output:



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






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Sep 7 at 7:02









                  josephzhong

                  11




                  11



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52186918%2fconverting-list-of-lists-into-a-dictionary-of-dictionaries-in-python%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay