0

Let's say I have a nested dict, e.g. the following

{'agent1': {'status': True}, 
 'block1': {'status': True, 'number': False, 'usable_by': True, 'location': True, 'skill':
                {'speed': False, 'flexibility': True}}}

At the lowest key level (the leaves) of this dict, the values are only boolean (True or False). The input dict can basically have any kind of nested structure with different names as keys and no fixed depth.

How can I check in general, whether there is False in a given dict.

eljobso
  • 352
  • 2
  • 6
  • 20

4 Answers4

2

You'd have to traverse the dictionaries, and you want to exit early:

def any_false_leaf(d):
    if isinstance(d, dict):
        return any(any_false_leaf(v) for v in d.values())
    return not d

This recurses through your dictionaries, and returns True if there is a nested false value in the structure. Using the any() function and a generator expression guarantees that the result is produced as soon as such a value is found.

Demo:

>>> d = {'agent1': {'status': True},
...  'block1': {'status': True, 'number': False, 'usable_by': True, 'location': True, 'skill':
...                 {'speed': False, 'flexibility': True}}}
>>> any_false_leaf(d)
True
>>> any_false_leaf({'foo': True})
False
>>> any_false_leaf({'foo': {'bar': True}})
False
>>> any_false_leaf({'foo': {'bar': True, 'spam': False}})
True
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

To traverse the nested dict, you can use recursion. See (Loop through all nested dictionary values?)

def contains_false(d):
    for k,v in d.iteritems():
        if isinstance(v, dict):
            # recurse into nested-dict
            if contains_false(v):
                return True

        # Check value of leaf-node. Exit early
        # if we find a 'False' value.
        if v is False:
            return True

   # no 'False' values found
   return False

>>> d = {1:True, 2:{1:True, 2:True}, 3:{1:True, 2:True, 3:{1:False}}}
>>> contains_false(d)
True
>>> d[3][3][1] = True
>>> contains_false(d)
False

This is assuming that you don't need to know the key(s) to reach the 'False' value.

Community
  • 1
  • 1
theorifice
  • 670
  • 3
  • 9
0

A quick solution can be:

d = {'block1': {'status': True, 'usable_by': True, 'skill': {'flexibility': True, 'speed': False}, 'number': False, 'location': True}, 'agent1': {'status': True}}

values = []

def find_false(d):
    for k in d.keys():
        if isinstance(d[k], dict):
            find_false(d[k])
        else:
            values.append(d[k])

find_false(d)
print(False in values)

Hope this helps.

Heval
  • 338
  • 3
  • 11
0

Convert your nested dictionary to a NestedDict

from ndicts.ndicts import NestedDict

d = {
    'agent1': {
        'status': True
    }, 
    'block1': {
        'status': True, 
        'number': False, 
        'usable_by': True, 
        'location': True, 
        'skill': {'speed': False, 'flexibility': True}
     }
}
nd = NestedDict(d)

Then get the answer with a one liner

>>> all(nd.values())
False

To install ndicts pip install ndicts

edd313
  • 1,109
  • 7
  • 20