【发布时间】:2011-05-04 20:42:32
【问题描述】:
我的字典如下:
someDict = {'a':[], 'b':[]}
我想确定这本字典是否有任何非空列表的值。如果是这样,我想返回 True。如果没有,我想返回 False。有什么方法可以使它成为一个衬里吗?
【问题讨论】:
-
嗯,我们在这里被困在 Python 2.4.1 上,所以 'any' 不起作用,但是下面有很多解决方案可以工作。
标签: python
我的字典如下:
someDict = {'a':[], 'b':[]}
我想确定这本字典是否有任何非空列表的值。如果是这样,我想返回 True。如果没有,我想返回 False。有什么方法可以使它成为一个衬里吗?
【问题讨论】:
标签: python
根据我的测试,以下单行(我的原始答案)在所有情况下都具有最佳时间性能。有关测试信息,请参阅下面的编辑。我确实承认使用生成器表达式的解决方案将更加节省内存,并且应该是大型字典的首选。
编辑:这是一个老化的答案,我的测试结果可能对最新版本的 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 的一长串值。
看看当 dict 变大时会发生什么:
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
但这还不够 - 最坏的“错误”情况呢?
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
【讨论】:
非虚假或非空列表:
不假:
any(someDict.values())
非空列表:
any(a != [] for a in someDict.values())
或
any(map(lambda x: x != [], someDict.values()))
或者,如果您可以接受错误的返回值:
filter(lambda x: x != [], someDict.values())
返回一个非空列表的项目列表,因此如果它们都是空列表,则它是一个空列表:)
【讨论】:
字面意思:
any(x != [] for x in someDict.itervalues())
【讨论】:
试试这个
all([d[i] == [] for i in d])
编辑:哎呀,我想我让你倒退了。让deMorgan那
any([d[i] != [] for i in d])
无论如何,第二种方式比第一种方式具有短路优势
【讨论】:
False 表达式时也会短路。
>>> someDict = {'a':[], 'b':[]}
>>> all(map(lambda x: x == [], someDict.values()))
True
【讨论】:
s/list comprehension/generator expression/.
dict(('a'*i, [i]) for i in range(10000)) 进行基准测试)。您还保存了两个括号;)
len(filter(lambda x: x!=[], someDict.values())) != 0
【讨论】: