views:

68

answers:

3

I would like to turn the following dictionary:

dictionary = {
    4388464: ['getting']
    827862 : ['Taruma', 'Varuna']
    ...
}

into:

dictionary = {
    4: {3: {8: {8: {4: {6: {4: {'words': ['getting']}}}}}}}
    8: {2: {7: {8: {6: {2: {'words': ['Taruma', 'Varuna']}}}}}}
    ...
}

This will then allow me to use the dictionary like: dictionary[8][2][7][8][6][2]['words'] instead of: dictionary[827862].

+5  A: 
import pprint

dictionary = {
    4388464: ['getting'],
    43881: ['got'],
    827862 : ['Taruma', 'Varuna'],
}

d2 = {}

def add_it(d, k, words):
    knum = int(k[0])
    if len(k) == 1:
        d[knum] = {'words': words}
    else:
        dsub = d.setdefault(knum, {})
        add_it(dsub, k[1:], words)

for k, words in dictionary.items():
    add_it(d2, list(str(k)), words)


pprint.pprint(d2)

prints:

{4: {3: {8: {8: {1: {'words': ['got']},
                 4: {6: {4: {'words': ['getting']}}}}}}},
 8: {2: {7: {8: {6: {2: {'words': ['Taruma', 'Varuna']}}}}}}}
Ned Batchelder
A: 

A short solution to produce the dictionaries:

def num2dict( n, d ):
  if n < 10:
    return { n: d }
  else:
    q, r = divmod( n, 10 )
    return num2dict( q, { r: d } )

print( num2dict( 4388464, { 'words': [ 'getting' ] } ) )
mkluwe
Of course this will blow up if another entry that starts with the same digit is added to the new dictionary.
Tim Pietzcker
Yes, I wrote this before it became clear what the dictionaries should be used for.
mkluwe
A: 

You could try using a recursive defaultdict:

from collections import defaultdict

# define a hierarchical defaultdict (of defaultdicts (of defaultdicts...))
class recursivedefaultdict(defaultdict):
    def __init__(self):
        self.default_factory = type(self)

# add an iterator recursively to create entries, sub-entries, etc.
def addToTree(it, v, accum):
    try:
        addToTree(it, v, accum[it.next()])
    except StopIteration:
        accum["words"] = v

# test it out
dictionary = { 
    4388464: ['getting'], 
    43881: ['got'], 
    827862 : ['Taruma', 'Varuna'], 
} 

d2 = recursivedefaultdict()
for k,v in dictionary.iteritems():
    addToTree(iter(str(k)), v, d2)


# use recursion again to view the results
def dumpDict(d,indent=""):
    for k,v in d.iteritems():
        if k == "words":
            print "%s- %s : %s" % (indent, k, v)
        else:
            print "%s- %s:" % (indent, k)
            dumpDict(v, indent+"  ")

dumpDict(d2)

Gives:

- 8:
  - 2:
    - 7:
      - 8:
        - 6:
          - 2:
            - words : ['Taruma', 'Varuna']
- 4:
  - 3:
    - 8:
      - 8:
        - 1:
          - words : ['got']
        - 4:
          - 6:
            - 4:
              - words : ['getting']

I think a recursive defaultdict is a beautiful way to create these nested dicts of unpredictable length. (Note that there will be trouble though, if the next value we add uses 43884 as the key, as there already exists an entry for d2[4][3][8][8][4].)

Paul McGuire