Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One liner to determine if dictionary values are all empty lists or not

Tags:

python

I have a dict as follows:

someDict = {'a':[], 'b':[]}

I want to determine if this dictionary has any values which are not empty lists. If so, I want to return True. If not, I want to return False. Any way to make this a one liner?

like image 429
Nathan Avatar asked May 04 '11 20:05

Nathan


People also ask

How do you check if all values in dictionary are empty?

You can use the [any()] 1 method, basically it checks for boolean parameters, but 0 will act as False in this case, and any other number as True. Edit 2: one sidenote/caution, calling any() with an empty list of elements will return False.

How do you check if a list in a dict is empty Python?

The preferred way to check if any list, dictionary, set, string or tuple is empty in Python is to simply use an if statement to check it. def is_empty(any_structure): if any_structure: print('Structure is not empty.

How do you check if a list is empty?

Empty lists are considered False in Python, hence the bool() function would return False if the list was passed as an argument. Other methods you can use to check if a list is empty are placing it inside an if statement, using the len() methods, or comparing it with an empty list.

How do I check if a 2d list is empty in Python?

You can check if the list is empty in python using the bool() function. bool() function returns boolean value of the specified object. The object will always return True , unless the object is empty, like [] , () , {} . You can use the bool() function for any of the list-like objects.


2 Answers

Per my testing, the following one-liner (my original answer) has best time performance in all scenarios. See edits below for testing information. I do acknowledge that solutions using generator expressions will be much more memory efficient and should be preferred for large dicts.

EDIT: This is an aging answer and the results of my testing may not be valid for the latest version of python. Since generator expressions are the more "pythonic" way, I'd imagine their performance is improving. Please do your own testing if you're running this in a 'hot' codepath.

bool([a for a in my_dict.values() if a != []])

Edit:

Decided to have some fun. A comparison of answers, not in any particular order:

(As used below, timeit will calculate a loop order of magnitude based on what will take less than 0.2 seconds to run)

bool([a for a in my_dict.values() if a != []]) :

python -mtimeit -s"my_dict={'a':[],'b':[]}" "bool([a for a in my_dict.values() if a != []])"
1000000 loops, best of 3: 0.875 usec per loop

any([my_dict[i] != [] for i in my_dict]) :

python -mtimeit -s"my_dict={'a':[],'b':[]}" "any([my_dict[i] != [] for i in my_dict])"
1000000 loops, best of 3: 0.821 usec per loop

any(x != [] for x in my_dict.itervalues()):

python -mtimeit -s"my_dict={'a':[],'b':[]}" "any(x != [] for x in my_dict.itervalues())"
1000000 loops, best of 3: 1.03 usec per loop

all(map(lambda x: x == [], my_dict.values())):

python -mtimeit -s"my_dict={'a':[],'b':[]}" "all(map(lambda x: x == [], my_dict.values()))"
1000000 loops, best of 3: 1.47 usec per loop

filter(lambda x: x != [], my_dict.values()):

python -mtimeit -s"my_dict={'a':[],'b':[]}" "filter(lambda x: x != [], my_dict.values())"
1000000 loops, best of 3: 1.19 usec per loop



Edit again - more fun:

any() is best case O(1) (if bool(list[0]) returns True). any()'s worst case is the "positive" scenario - a long list of values for which bool(list[i]) returns False.


Check out what happens when the dict gets big:

bool([a for a in my_dict.values() if a != []]) :

#n=1000
python -mtimeit -s"my_dict=dict(zip(range(1000),[[]]*1000))" "bool([a for a in my_dict.values() if a != []])"
10000 loops, best of 3: 126 usec per loop

#n=100000
python -mtimeit -s"my_dict=dict(zip(range(100000),[[]]*100000))" "bool([a for a in my_dict.values() if a != []])"
100 loops, best of 3: 14.2 msec per loop

any([my_dict[i] != [] for i in my_dict]):

#n=1000
python -mtimeit -s"my_dict=dict(zip(range(1000),[[]]*1000))" "any([my_dict[i] != [] for i in my_dict])"
10000 loops, best of 3: 198 usec per loop

#n=100000
python -mtimeit -s"my_dict=dict(zip(range(100000),[[]]*100000))" "any([my_dict[i] != [] for i in my_dict])"
10 loops, best of 3: 21.1 msec per loop



But that's not enough - what about a worst-case 'False' scenario?

bool([a for a in my_dict.values() if a != []]) :

python -mtimeit -s"my_dict=dict(zip(range(1000),[0]*1000))" "bool([a for a in my_dict.values() if a != []])"
10000 loops, best of 3: 198 usec per loop

any([my_dict[i] != [] for i in my_dict]) :

python -mtimeit -s"my_dict=dict(zip(range(1000),[0]*1000))" "any([my_dict[i] != [] for i in my_dict])"
1000 loops, best of 3: 265 usec per loop
like image 145
Ben Burns Avatar answered Sep 18 '22 14:09

Ben Burns


Not falsey or not empty lists:

Not falsey:

any(someDict.values())

Not empty lists:

any(a != [] for a in someDict.values())

or

any(map(lambda x: x != [], someDict.values()))

Or if you are ok with a falsey return value:

filter(lambda x: x != [], someDict.values())

Returns a list of items that are not empty lists, so if they are all empty lists it's an empty list :)

like image 23
Henry Avatar answered Sep 21 '22 14:09

Henry