azazelspeaks
azazelspeaks

Reputation: 6045

Get all nth level elements of dictionary

I'm trying to create a list of all nth level elements of a dictionary.

I'd prefer the solution to be generic for the nth item, though my example below lists two levels.

If you imagine the problem as the image below:

enter image description here

I am trying to get a list of all the values from 16-31.

For example, I have a dictionary of i randomly generated Houses with j taps and I need to find out if any of the taps are on.

Is there a way to create a list of all the tap outputs for me to just search through using:

for i in list_of_tap_outputs:
    new_list+=lambda x:x[2]

or something else or do I have to resign myself to using lists. I'd also like to be able to track which tap was on in the whole system. If I used lists, I'd have to remember which tap was assigned which index in the list and do not want to do that.

data={'House'+str(i): {"Tap"+str(j): 'on' if random.randint(1,2)%2==1 else 'off'
                        for j in range(4)} for i in range(3)}

print data

with output like this:

{'House2': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'off', 'Tap2': 'off'},
'House0': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'on', 'Tap2': 'on'},
'House1': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'off', 'Tap2': 'on'}}

Upvotes: 0

Views: 532

Answers (4)

martineau
martineau

Reputation: 123491

I'm not sure what more than two "levels" would look like, but it's pretty simple for 1 of them:

from pprint import pprint
import random

data={'House'+str(i): {"Tap"+str(j): 'on' if random.randint(1,2)%2==1 else 'off'
                        for j in range(4)} for i in range(3)}

def get_nth_level_elements(d):
    results = []
    for key, value in d.items():
        results.append(value)
    return results

results = get_nth_level_elements(data)
pprint(results)

Output:

[{'Tap0': 'on', 'Tap1': 'off', 'Tap2': 'on', 'Tap3': 'off'},
 {'Tap0': 'on', 'Tap1': 'off', 'Tap2': 'on', 'Tap3': 'off'},
 {'Tap0': 'on', 'Tap1': 'on', 'Tap2': 'off', 'Tap3': 'on'}]

Upvotes: 0

TallChuck
TallChuck

Reputation: 1972

So, you seem to be asking two questions here, and rather than focusing on the use case with the house and the taps, in this answer, I'll try to address the general case.

I'm no expert on Python implementation details, nor am I familiar with all the builtin functions and standard libraries, but I think the only practical way to generate a list like you are talking about would be by use of a recursive function. You seem to be looking at this problem a lot like a search tree, and you can find plenty of reading on those if you care enough to look into it.

Here's an example function that should do the job. I haven't tested extensively, but it at least works for the sample data you gave.

def extract_nth_level(root, n):
    if n == 0:
        return [root]
    values = []
    if isinstance(root, dict):
        for subtree in root.values():
            values += extract_nth_level(subtree, n-1)
    return values

data = {
    'House2': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'off', 'Tap2': 'off'},
    'House0': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'on', 'Tap2': 'on'},
    'House1': {'Tap1': 'off', 'Tap0': 'on', 'Tap3': 'off', 'Tap2': 'on'}
}

print extract_nth_level(data, 2)

This prints the following list:

['off', 'on', 'off', 'off', 'off', 'on', 'on', 'on', 'off', 'on', 'off', 'on']

Upvotes: 0

Mark Tolonen
Mark Tolonen

Reputation: 177901

Check for any tap on:

any('on' in taps.values() for taps in data.values())

Check for a particular tap on in any house:

any(taps['Tap0'] == 'on' for taps in data.values())

You can use all() to check for all taps on as well.

Upvotes: 2

TallChuck
TallChuck

Reputation: 1972

def any_tap_on(data):
    for house, taps in data.items():
        for tap, status in taps.items():
            if status == 'on':
                return True
    return False

Alternately, it could be faster to use the in keyword -- as far as order of complexity, it is the same, but builtin operations tend to run faster:

def any_tap_on(data):
    for house, taps in data.items():
        if 'on' in taps.values():
            return True
    return False

Upvotes: 2

Related Questions