title: Create a tree from multiple nested dictionaries/lists in Python
body: <p><strong>Preface</strong>: To help explain <strong>why</strong> I am doing this, I will explain the end goal. Essentially I have a list of <em>accounts</em> that are defined in a very specific syntax. Here are some examples:</p>
  
  <pre><code>Assets:Bank:Car
  Assets:Bank:House
  Assets:Savings:Emergency
  Assets:Savings:Goals:Roof
  Assets:Reserved
  </code></pre>
  
  <p>As can be seen above, an account can have any number of parents and children. The end goal is to parse the above accounts into a tree structure in Python that will be used for providing account auto-completion in the Sublime Text Editor (i.e, if I typed <em>Assets:</em> and then queried for auto-complete, I would be presented with a list as such: <em>Bank, Savings, Reserved</em>)</p>
  
  <p><strong>The Result:</strong> Using the account list from the preface, the desired result in Python would look something like below:</p>
  
  <pre><code>[  
     {  
        "Assets":[  
           {  
              "Bank":[  
                 "Car",
                 "House"
              ]
           },
           {  
              "Savings":[  
                 "Emergency",
                 {  
                    "Goals":[  
                       "Roof"
                    ]
                 }
              ]
           },
           "Reserved"
        ]
     }
  ]
  </code></pre>
  
  <p><strong>Half-Solution:</strong> I was able to get two basic accounts to get added together using recursion. This works for adding these two: <code>Assets:Bank:Car</code> and <code>Assets:Bank:House</code>. However, once they start to differ it starts to fall apart and the recursion gets messy, so I'm not sure if it's the best way.</p>
  
  <pre><code>import re
  
  def parse_account(account_str):
      subs = account_str.split(":")
  
      def separate(subs):
          if len(subs) == 1:
              return subs
          elif len(subs):
              return [{subs[0]: separate(subs[1:])}]
  
      return separate(subs)
  
  def merge_dicts(a, b):
      # a will be a list with dictionaries and text values and then nested lists/dictionaries/text values
      # b will always be a list with ONE dictionary or text value
  
      key = b[0].keys()[0] # this is the dictionary key of the only dictionary in the b list
  
      for item in a: # item is a dictionary or a text value
          if isinstance(item, dict): # if item is a dictionary
              if key in item:
                  # Is the value a list with a dict or a list with a text value
                  if isinstance(b[0][key][0], str):
                      # Extend the current list with the new value
                      item[key].extend(b[0][key])
                  else:
                      # Recurse to the next child
                      merge_dicts(item[key], b[0][key])
              else:
  
  
      return a
  
  # Accounts have an "open [name]" syntax for defining them
  text = "open Assets:Bank:Car\nopen Assets:Bank:House\nopen Assets:Savings:Emergency\nopen Assets:Savings:Goals:Roof\nopen Assets:Reserved"
  EXP = re.compile("open (.*)")
  accounts = EXP.findall(text) # This grabs all accounts
  
  # Create a list of all the parsed accounts
  dicts = []
  for account in accounts:
      dicts.append(parse_account(account))
  
  # Attempt to merge two accounts together
  final = merge_dicts(dicts[0], dicts[1])
  print final
  
  # In the future we would call: reduce(merge_dicts, dicts) to merge all accounts
  </code></pre>
  
  <p>I could be going about this in the completely wrong way and I would be interested in differing opinions. Otherwise, does anyone have insight into how to make this work with the remaining accounts in the example string?</p>