3

I have a small example of a nested dictionary (in my case a collections defaultdict):

all_dict = {'d1': {'a': 2, 'b': 4, 'c': 10}, 
            'd2': {'a': 1, 'b': 23,'c': 0},
            'd3': {'a': 4, 'b': 12,'c': 4},
            'd4': {'a': 0, 'b': 4, 'c': 3},
            'd5': {'a': 4, 'b': 0, 'c': 1}}

And I would like to filter all the zero values in all_dict. In my real data, the nested dictionaries are very big. I would like any general "pythonic" solution. I tried some comprehension but I failed. I would like some like:

all_dict_filtered = 
           {'d1': {'a': 2, 'b': 4, 'c': 10}, 
            'd2': {'a': 1, 'b': 23},
            'd3': {'a': 4, 'b': 12,'c': 4},
            'd4': {'b': 4, 'c': 3},
            'd5': {'a': 4, 'c': 1}}

Any tip would be great. Thank you for your time and attention. Paulo

I have this but is ugly:

    filtered = defaultdict(dict)
    for k1, v1 in all_dict.items():
        for k2, v2 in v1.items():
            if v2 > 0:
                filtered[k1] = filtered.get(k1, {})
                filtered[k1][k2] = v2
defaultdict(dict,
            {'d1': {'a': 2, 'b': 4, 'c': 10},
             'd2': {'a': 1, 'b': 23},
             'd3': {'a': 4, 'b': 12, 'c': 4},
             'd4': {'b': 4, 'c': 3},
             'd5': {'a': 4, 'c': 1}})

4 Answers4

6

Simple one-liner using dict comprehensions:

import pprint

all_dict = {
    'd1': {'a': 2, 'b': 4, 'c': 10},
    'd2': {'a': 1, 'b': 23, 'c': 0},
    'd3': {'a': 4, 'b': 12, 'c': 4},
    'd4': {'a': 0, 'b': 4, 'c': 3},
    'd5': {'a': 4, 'b': 0, 'c': 1}
}

pprint.pprint({k: {key: value for key, value in v.items() if value != 0} for k, v in all_dict.items()})

Output:

{'d1': {'a': 2, 'b': 4, 'c': 10},
 'd2': {'a': 1, 'b': 23},
 'd3': {'a': 4, 'b': 12, 'c': 4},
 'd4': {'b': 4, 'c': 3},
 'd5': {'a': 4, 'c': 1}}
funnydman
  • 9,083
  • 4
  • 40
  • 55
5

Try:

all_dict = {
    "d1": {"a": 2, "b": 4, "c": 10},
    "d2": {"a": 1, "b": 23, "c": 0},
    "d3": {"a": 4, "b": 12, "c": 4},
    "d4": {"a": 0, "b": 4, "c": 3},
    "d5": {"a": 4, "b": 0, "c": 1},
}

for k, v in all_dict.items():
    all_dict[k] = {kk: vv for kk, vv in v.items() if vv != 0}

print(all_dict)

Prints:

{
    "d1": {"a": 2, "b": 4, "c": 10},
    "d2": {"a": 1, "b": 23},
    "d3": {"a": 4, "b": 12, "c": 4},
    "d4": {"b": 4, "c": 3},
    "d5": {"a": 4, "c": 1},
}
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
2

took me some time, but here you go:

dicty = {'d1': {'a': 2, 'b': 4, 'c': 10}, 
            'd2': {'a': 1, 'b': 23,'c': 0},
            'd3': {'a': 4, 'b': 12,'c': 4},
            'd4': {'a': 0, 'b': 4, 'c': 3},
            'd5': {'a': 4, 'b': 0, 'c': 1}}

listy = []

for value in dicty:
    for value2 in dicty[value]:
        if dicty[value][value2] == 0:
            listy.append((value, value2))   

for inpurity in listy:
    dicty[inpurity[0]].pop(inpurity[1])

print(listy)
print(dicty)
1

Try this:

import copy

all_dict = {'d1': {'a': 2, 'b': 4, 'c': 10}, 
            'd2': {'a': 1, 'b': 23,'c': 0},
            'd3': {'a': 4, 'b': 12,'c': 4},
            'd4': {'a': 0, 'b': 4, 'c': 3},
            'd5': {'a': 4, 'b': 0, 'c': 1}}

all_dict_filtered = copy.deepcopy(all_dict)

for i in all_dict:
    for j in all_dict[i] :
        if all_dict[i][j] == 0 :
            all_dict_filtered[str(i)].pop(str(j))

print(all_dict_filtered)

Output : {'d1': {'a': 2, 'b': 4, 'c': 10}, 'd2': {'a': 1, 'b': 23}, 'd3': {'a': 4, 'b': 12, 'c': 4}, 'd4': {'b': 4, 'c': 3}, 'd5': {'a': 4, 'c': 1}}

ghost21blade
  • 731
  • 2
  • 8
  • 21
  • 1
    The goal was to process all_dict to get all_dict_filtered. But, you are starting with a different different dictionary (i.e. tesdict has different contents than all_dict). – DarrylG Aug 07 '22 at 14:37
  • I'll edit it – ghost21blade Aug 07 '22 at 17:30
  • 1
    You could make adict equal the posted dictionary and test_dict a copy of it by `testdict = copy.deepcopy(adict)` (i.e. copy using the copy module). You don't want to use literal assignment for both dictionaries. – DarrylG Aug 07 '22 at 17:37
  • @DarrylG I edited the answer. Now it filters out zeros of ***all_dict*** and output as ***all_dict_filterd*** – ghost21blade Aug 09 '22 at 08:43