Aesthete
Aesthete

Reputation: 18848

Python dict restructure

Given the following data structure:

out = {
  'foo': { 'public':{}, 'private':{}, 'other':{} },
  'bar': { 'public':{}, 'private':{}, 'other':{} }
}

I am attempting to slice out parts of the sub-structure to create a new dict. My use for this is to respond to requests with all data except that marked private.

To do the opposite is trivial:

response = {x,y['private'] for x,y in out.iteritems()}

Which constructs a dict for each foo and bar containing only the data marked private. But is there some functionality in the standard library (itertools perhaps) that would produce the following:

out = {
  'foo': { 'public':{}, 'other':{} },
  'bar': { 'public':{}, 'other':{} }
}

I have tried the following:

{x:(y['public'], y['other']) for x,y in out.iteritems()}

Although I would prefer to not use a tuple, and not explicitly name each sub-structure, as this is not reusable or scalable.

def remove(name, obj):
    return {x:y for x,y in obj.iteritems() if x is not name}
{x:remove('private',y) for x,y in out.iteritems()}

This seems to work, but is there a better way? Any ideas?

Upvotes: 0

Views: 2073

Answers (3)

Duncan
Duncan

Reputation: 95722

Try this:

response = {}
for x,y in out.iteritems():
    response[x] = dict(y)
    del response[x]['private']

If you don't mind destroying the original dictionary then just iterate over it del'ing the 'private' elements, otherwise you need to copy the second level dicts and then del the unwanted items.

Upvotes: 0

Austin Phillips
Austin Phillips

Reputation: 15776

You can break this down into parts; you want a new dictionary which has some parts removed. So create a function which can return a dictionary without the elements in question and call this is part of an iterator.

You're using dictionary comprehensions so something like this would work:

def remove_items(d, *items):
    """
    Return dictionary copy with some items removed.
    """
    return { a: b for a, b in d.iteritems() if a not in items }

print { x: remove_items(y, 'private') for x, y in out.iteritems() }

Upvotes: 2

unddoch
unddoch

Reputation: 6004

Would that be what you mean?

respose = {x:{'public': y['public'], 'other': y['other']} for x,y in out.iteritems()}

Upvotes: 0

Related Questions