agftrading
agftrading

Reputation: 854

Remove items from nested dictionary where value is zero

Here is a nested dictionary:

fdict = {}
fdict['apple'] = {}
fdict['banana'] = {}

fdict['apple']['green'] = 5
fdict['apple']['red'] = 0
fdict['banana']['light_yellow'] = 10
fdict['banana']['dark_yellow'] = 0
fdict['appraisal round'] = 1

{'apple': {'green': 5, 'red': 0},
 'banana': {'light_yellow': 10, 'dark_yellow': 0},
 'appraisal round': 1}

What is the most pythonic way to remove the key and value pairs where the value is zero from this nested dictionary such that the following dictionary results:

{'apple': {'green': 5}, 'banana': {'light_yellow': 10}, 'appraisal round': 1}

Note: The appraisal round key does not have a dictionary as a value itself.

Here is what I have implemented so far:

overall_dict = {}
for key in [key for key in fdict.keys() if key != 'appraisal round']:
    new_dict = {k:v for k,v in fdict[key].items() if v != 0}
    overall_dict[key] = new_dict
overall_dict['appraisal round'] = 1

However, using a temporary dictionary, constructing an entirely new dictionary and adding back in the appraisal round does not seem like a clean approach. Is there perhaps a way to amend the existing dictionary more effectively?

Upvotes: 0

Views: 260

Answers (2)

Giannis Clipper
Giannis Clipper

Reputation: 707

I suggest the following solution (it works for multiple nested levels):

fdict = {
    'apple': {'green': 5, 'red': 0},
    'banana': {'light_yellow': 10, 'dark_yellow': 0},
    'appraisal round': 1
}

noZero = lambda d: { k1: noZero(v1) if isinstance(v1, dict) else v1 for k1, v1 in d.items() if v1 }

print(noZero(fdict))  # {'apple': {'green': 5}, 'banana': {'light_yellow': 10}, 'appraisal round': 1}

Upvotes: 2

Nf4r
Nf4r

Reputation: 1410

Assuming that You do not know the key that has non-dict type, a solution could be:

fdict = {}
fdict['apple'] = {}
fdict['banana'] = {}

fdict['apple']['green'] = 5
fdict['apple']['red'] = 0
fdict['banana']['light_yellow'] = 10
fdict['banana']['dark_yellow'] = 0
fdict['appraisal round'] = 1

def non_zero_value(item):
  k, v = item
  return v != 0

result = {}
for k, v in fdict.items():
  if isinstance(v, dict):
    result[k] = dict(filter(non_zero_value, v.items()))
  else:
    result[k] = v

print(result)
# {'apple': {'green': 5}, 'banana': {'light_yellow': 10}, 'appraisal round': 1}

Upvotes: 1

Related Questions