Reputation: 6045
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:
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
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
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
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
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