4

What would be the easiest way to go about turning this dictionary:

{'item':{'w':{'c':1, 'd':2}, 'x':120, 'y':240, 'z':{'a':100, 'b':200}}}

into this one:

{'item':{'y':240, 'z':{'b':200}}}

given only that you need the vars y and b while maintaining the structure of the dictionary? The size or number of items or the depth of the dictionary should not matter, as the one I'm working with can be anywhere from 2 to 5 levels deep.

EDIT: I apologize for the type earlier, and to clarify, I am given an array of strings (eg ['y', 'b']) which I need to find in the dictionary and then keep ONLY 'y' and 'b' as well as any other keys in order to maintain the structure of the original dictionary, in this case, it would be 'z'

A better example can be found here where I need Chipset Model, VRAM, and Resolution.

In regards to the comment, the input would be the above link as the starting dictionary along with an array of ['chipset model', 'vram', 'resolution'] as the keep list. It should return this:

{'Graphics/Displays':{'NVIDIA GeForce 7300 GT':{'Chipset Model':'NVIDIA GeForce 7300 GT', 'Displays':{'Resolution':'1440 x 900 @ 75 Hz'}, 'VRAM (Total)':'256 Mb'}}
tekulvw
  • 43
  • 3
  • I need y and b, but z has to stay to maintain the structure of the original dictionary. I don't want JUST the values of y and b, rather, I need the structure and values – tekulvw Dec 23 '13 at 20:53
  • Write a input and a desired ouput. And write as well examples of non desired ouput. Cause I'm lost here. – Bite code Dec 23 '13 at 21:16

4 Answers4

1

Assuming that the dictionary you want to assign to an element of a super-dictionary is foo, you could just do this:

my_dictionary['keys']['to']['subdict']=foo

Regarding your edit—where you need to eliminate all keys except those on a certain list—this function should do the trick:

def drop_keys(recursive_dict,keep_list):
    key_list=recursive_dict.keys()
    for key in key_list:
        if(type(recursive_dict[key]) is dict):
            drop_keys(recursive_dict[key], keep_list)
        elif(key not in keep_list):
            del recursive_dict[key]
Dan
  • 12,157
  • 12
  • 50
  • 84
  • I don't believe I was being clear enough before, sorry, but this won't work given an array of values I need to search for while keeping the structure of the original dictionary – tekulvw Dec 23 '13 at 21:05
  • after changing elif(recursive_dict[key] to elif(key.lower() it works perfectly, thank you! – tekulvw Dec 23 '13 at 21:30
1

Something like this?

d = {'item': {'w': {'c': 1, 'd': 2}, 'x': 120, 'y': 240, 'z': {'a': 100, 'b': 200}}}
l = ['y', 'z']
def do_dict(d, l):
    return {k: v for k, v in d['item'].items() if k in l}
mackwerk
  • 1,689
  • 4
  • 21
  • 44
  • It's closer, this will work for a dictionary with only two levels but not for one with any number of levels, I added a better example – tekulvw Dec 23 '13 at 21:11
1

Here's what I arrived at for a recursive solution, which ended up being similar to what @Dan posted:

def recursive_del(d,keep):
    for k in d.copy():
        if type(d[k]) == dict:
            recursive_del(d[k],keep)
            if len(d[k]) == 0: #all keys were deleted, clean up empty dict
                del d[k]
        elif k not in keep:
            del d[k]

demo:

>>> keepset = {'y','b'}
>>> a = {'item':{'w':{'c':1, 'd':2}, 'x':120, 'y':240, 'z':{'a':100, 'b':200}}}
>>> recursive_del(a,keepset)
>>> a
{'item': {'z': {'b': 200}, 'y': 240}}

The only thing I think he missed is that you will need to sometimes need to clean up dicts which had all their keys deleted; i.e. without that adjustment you would end up with a vestigial 'w':{} in your example output.

roippi
  • 25,533
  • 4
  • 48
  • 73
  • Yep that was one of the things I added, Dan answered first so I will give him credit. Thank you both for the help! – tekulvw Dec 23 '13 at 21:35
0

Using your second example I made something like this, it's not exactly pretty but it should be easy to extend. If your tree starts to get big, you can define some sets of rules to parse the dict.

Each rule here are actually pretty much "what should I do when i'm in which state".

def rule2(key, value):
    if key == 'VRAM (Total)':
        return (key, value)
    elif key == 'Chipset Model':
        return (key, value)

def rule1(key, value):
    if key == "Graphics/Displays":
        if isinstance(value, dict):
            return (key, recursive_checker(value, rule1))
        else:
            return (key, value)
    else:
        return (key, recursive_checker(value, rule2))

def recursive_checker(dat, rule):

    def inner(item):
        key = item[0]
        value = item[1]

        return rule(key, value)

    return dict(filter(lambda x: x!= None, map(inner, dat.items())))

# Important bits    
print recursive_checker(data, rule1)

In your case, as there is not many states, it isn't worth doing it but in case you have multiple cards and you don't necessarly know which key should be traversed but only know that you want certain keys from the tree. This method could be used to search the tree easily. It can be applied to many things.

Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99