eljobso
eljobso

Reputation: 362

Check whether a nested dict is False in the leaf nodes in python

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.

Upvotes: 1

Views: 1431

Answers (4)

edd313
edd313

Reputation: 1459

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

Upvotes: 0

theorifice
theorifice

Reputation: 690

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.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1122372

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

Upvotes: 3

Heval
Heval

Reputation: 348

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.

Upvotes: 0

Related Questions