0

I have a list of product categories which I want to convert to a dictionary.

['Livestock']
['Livestock', 'Poultry']
['Livestock', 'Poultry', 'Chickens']
['Livestock', 'Ruminants']
['Livestock', 'Ruminants', 'Goats']
['Livestock', 'Ruminants', 'Cows']
['Grocery']
['Grocery', 'Food Cupboard']
['Grocery', 'Food Cupboard', 'Canned & Jarred Foods']
['Grocery', 'Food Cupboard', 'Canned & Jarred Foods', 'Soup']
['Grocery', 'Food Cupboard', 'Canned & Jarred Foods', 'Vegetables']

My expected dictionary should look like:

{ 
  Livestock: 
   {
    Poultry: [Chickens],
    Ruminants: [Goats, Cows]
 },
 Grocery:{ 
    Food Cupboard: {
      Canned & Jarred Foods: [Soup,Vegetables ]
   }
  }
}
0n10n_
  • 382
  • 3
  • 10
  • What have you tried? What did not work? Post your code. – DYZ Aug 26 '22 at 02:36
  • See https://stackoverflow.com/questions/14692690/access-nested-dictionary-items-via-a-list-of-keys for how you can create nested dictionaries from a list. the only difference in your case is that the leaf elements are lists that you append to, rather than strings that you just assign. – Barmar Aug 26 '22 at 02:37

1 Answers1

0

If you don't care too much about raw speed, this is a fairly simple solution:

cats = [
    ['Livestock'],
    ['Livestock', 'Poultry'],
    ['Livestock', 'Poultry', 'Chickens'],
    ['Livestock', 'Ruminants'],
    ['Livestock', 'Ruminants', 'Goats'],
    ['Livestock', 'Ruminants', 'Cows'],
    ['Grocery'],
    ['Grocery', 'Food Cupboard'],
    ['Grocery', 'Food Cupboard', 'Canned & Jarred Foods'],
    ['Grocery', 'Food Cupboard', 'Canned & Jarred Foods', 'Soup'],
    ['Grocery', 'Food Cupboard', 'Canned & Jarred Foods', 'Vegetables']
]

# only keep lists that aren't the start of another
cats = [c for c in cats if not any(sc[:len(c)] == c for sc in cats if sc != c)]

result = {}
for *nodes, last, leaf in categories:
    current = result
    for node in nodes:
        if node not in current:
            current[node] = {}
        current = current[node]
    if last not in current:
        current[last] = []
    current[last].append(leaf)

print(result)

Output:

{'Livestock': {'Poultry': ['Chickens'], 'Ruminants': ['Goats', 'Cows']}, 'Grocery': {'Food Cupboard': {'Canned & Jarred Foods': ['Soup', 'Vegetables']}}}

Note that this assumes you never pass something like this:

cats = [
    ['apple'],
    ['banana']
]

And then expect something like this:

['apple', 'banana']

The solution expects that there's always at least a single level of dictionary keys.

Grismar
  • 27,561
  • 4
  • 31
  • 54