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

前端 未结 6 888
-上瘾入骨i
-上瘾入骨i 2021-01-01 22:24

I have a dict as follows:

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

I want to determine if this dictionary has any values which are not empty lists.

相关标签:
6条回答
  • 2021-01-01 22:47

    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
    
    0 讨论(0)
  • 2021-01-01 22:50
    len(filter(lambda x: x!=[], someDict.values())) != 0
    
    0 讨论(0)
  • 2021-01-01 23:02

    Quite literally:

    any(x != [] for x in someDict.itervalues())
    
    0 讨论(0)
  • 2021-01-01 23:02

    try this

     all([d[i] == [] for i in d])
    

    edit: oops, i think i got you backwards. lets deMorgan that

    any([d[i] != [] for i in d])
    

    this second way has the short-circuit advantage on the first anyhow

    0 讨论(0)
  • 2021-01-01 23:03
    >>> someDict = {'a':[], 'b':[]} 
    >>> all(map(lambda x: x == [], someDict.values()))
    True
    
    0 讨论(0)
  • 2021-01-01 23:11

    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 :)

    0 讨论(0)
提交回复
热议问题