2

I use Python 3

I want to check if all of my tested values in the nested dictionary are non 0.

So here is the simplified example dict:

d = {'a': {'1990': 10, '1991': 0, '1992': 30},
     'b': {'1990': 15, '1991': 40, '1992': 0}}

and I want to test if for both dicts 'a' and 'b' the values of the keys '1990' and '1991' are not zero

for i in d:
    for k in range(2):
        year = 1990
        year = year + k
        if all((d[i][str(year)]) != 0):
            print(d[i])

so it should only return b, because a['1991']=0

but this is the first time I work with the all() function and I get the error core: TypeError: 'bool' object is not iterable

the error is in the if all() line

thank you very much!

TDot
  • 21
  • 1
  • 4
  • Possible duplicate of [How do Python's any and all functions work?](http://stackoverflow.com/questions/19389490/how-do-pythons-any-and-all-functions-work) – juanpa.arrivillaga Apr 13 '17 at 22:56
  • Before I posted my question, I looked at this thread, but it only helped a liddle. Theoretically the all function is the right operator for my needs. But somehow Im not giving the all function iterable. But I thought by running the for loop, I do this is not working as well: `tr = all((d[i][str(year)]) != 0) if tr: print(d[i])` – TDot Apr 13 '17 at 23:11
  • Then your real issue is understanding what an iterable is, and how to pass it. `(d[i][str(year)]) != 0` is a `bool`, so you need to pass something like a list to `all` – juanpa.arrivillaga Apr 13 '17 at 23:37

1 Answers1

0

This can done a bit more generally with a list comprehension where you iterate over the items in dict d. A simple comprehension to iterate over the keys and values in our dictionary looks like this:

>>> [k for k, v in d.items()]
['a', 'b']

In the above k will contain the keys and v the values. The comprehension also has an if clause. With that you can filter out the items you don't want. So we define years = ('1990', '1991'). Now we can do another comprehension to test our year values.

To iterate over only 'a', we could do this:

>>> [d['a'][y] for y in years] 
[10, 0]
>>> all([d['a'][y] for y in years])
False

Gluing the whole thing together:

>>> d={'a' :{ '1990': 10, '1991':0, '1992':30},'b':{ '1990':15, '1991':40, '1992':0}}
>>> years = ('1990', '1991')
>>> [k for k, v in d.items() if all([v[y] for y in years])]
['b']

See the python docs for more information on list comprehensions.

Brad Campbell
  • 2,969
  • 2
  • 23
  • 21
  • thanks! it worked in my bigger code as well. I definitly will have to learn many things regarding python. It took me a while to understand that 0 is false and therefore in your code no argument is needed in my bigger code, I have many more years, thats why I used the range function. Do you still think just writing them all down in a list (or tuple like you did), is best? – TDot Apr 13 '17 at 23:42
  • If the set of years won't change, then that would fine. If you wanted to build a set of all of the years you have in your data structure you could use a `set` object and the `chain` method from the `itertools` package (part of the standard library) for that `set(it.chain(*[d[di].keys() for di in d]))` – Brad Campbell Apr 17 '17 at 18:31
  • If this solved your problem can you please accept the answer? – Brad Campbell May 11 '17 at 12:44