基于简单的列表理解:
yay = [ i for i in a if a[i] ]
nay = [ i for i in a if not a[i] ]
Run Code Online (Sandbox Code Playgroud)
我想知道是否有办法同时分配yay和nay值(即有条件的命中和未命中)?
看起来像这样的东西
( yay , nay ) = ...
Run Code Online (Sandbox Code Playgroud)
我对可读性和速度感到好奇(看到两个列表推导比单个for循环附加到列表中的速度快5%,我感到有些惊讶)
更新:
最初的例子是在dict中获取"true"和"false"有价值键的列表...
a = {i: i >= 50 for i in range(100)}
yay = [k for k, v in a.items() if v]
nay = [k for k, v in a.items() if not v]
Run Code Online (Sandbox Code Playgroud)
这里通常的解决方案是不要全神贯注于使用列表理解的想法.只需使用一个for循环:
yay, nay = [], []
for i in a:
if somecondition(i):
yay.append(i)
else:
nay.append(i)
Run Code Online (Sandbox Code Playgroud)
如果你发现自己做了很多,那么只需将代码移到一个函数中:
def yesno(seq, cond):
yay, nay = [], []
for i in seq:
if cond(i):
yay.append(i)
else:
nay.append(i)
return yay, nay
yay, nay = yesno(a, lambda x: a[x])
Run Code Online (Sandbox Code Playgroud)
评论表明这比列表理解慢.将条件作为lambda传递将不可避免地受到重创,我不认为你可以做很多事情,但是一些性能打击可能来自查找append方法并且可以改进:
def yesno(seq, cond):
yay, nay = [], []
yes, no = yay.append, nay.append
for i in seq:
if cond(i):
yes(i)
else:
no(i)
return yay, nay
Run Code Online (Sandbox Code Playgroud)
我不知道这是否会带来很大的不同,但定时它可能会很有趣.
在评论中@martineau建议使用生成器并使用它any().我会在这里包含它,但我会any用itertools配方代替使用迭代器:
def consume(iterator, n):
"Advance the iterator n-steps ahead. If n is none, consume entirely."
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(islice(iterator, n, n), None)
Run Code Online (Sandbox Code Playgroud)
然后你可以写:
yay, nay = [], []
consume((yay if a[i] else nay).append(i) for i in a)
Run Code Online (Sandbox Code Playgroud)