一行代码判断字典值是否全为空列表

16 投票
6 回答
18471 浏览
提问于 2025-04-16 17:00

我有一个字典,内容如下:

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

我想检查这个字典里是否有任何值不是空列表。如果有,我想返回True;如果没有,我想返回False。有没有办法把这个操作写成一行代码呢?

6 个回答

6

字面意思就是:

any(x != [] for x in someDict.itervalues())
13

不是假值或者不是空列表:

不是假值:

any(someDict.values())

不是空列表:

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

或者

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

或者如果你可以接受假值的返回结果:

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

返回一个包含非空列表的项目列表,如果所有的列表都是空的,那返回的就是一个空列表哦 :)

16

根据我的测试,下面这个一行代码(我最初的答案)在所有情况下的运行速度都是最好的。下面的编辑部分有测试信息。我承认,使用生成器表达式的解决方案在内存使用上会更高效,尤其是对于大的字典,应该优先考虑。

编辑:这个答案已经有些年头了,我的测试结果可能不适用于最新版本的Python。由于生成器表达式是更“Pythonic”的方式,我想它们的性能可能在不断提升。如果你在一个频繁运行的代码中使用这些,建议你自己进行测试。

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

编辑:

决定玩得开心一点。下面是一些答案的比较,没有特定顺序:

(在下面使用的timeit会计算一个循环的数量级,基于运行时间少于0.2秒的情况)

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



再编辑 - 更有趣的内容:

any()的最佳情况是O(1)(如果bool(list[0])返回True)。any()的最坏情况是“积极”场景 - 一长串值中bool(list[i])返回False。


看看当字典变大时会发生什么:

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



但这还不够 - 那最坏的“False”场景呢?

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

撰写回答