我知道如何在单独的行上同时使用 for 循环和 if 语句,例如:
>>> a = [2,3,4,5,6,7,8,9,0]
... xyz = [0,12,4,6,242,7,9]
... for x in xyz:
... if x in a:
... print(x)
0,4,6,7,9
而且我知道当语句很简单时,我可以使用列表推导来组合这些,例如:
print([x for x in xyz if x in a])
但是我在任何地方都找不到一个很好的例子(可以复制和学习),它展示了在 for 循环和一些 if 语句的组合之后发生的一组复杂的命令(不仅仅是“打印 x”)。我期望的东西看起来像:
for x in xyz if x not in a:
print(x...)
这不是python应该工作的方式吗?
for
循环和 if
语句。
a
是一个列表,则 x in a
很慢。
根据 The Zen of Python(如果您想知道您的代码是否是“Pythonic”,那就去那里):
美丽总比丑陋好。
显式优于隐式。
简单胜于复杂。
平面优于嵌套。
可读性很重要。
获取两个 set
的 sorted
intersection
的 Pythonic 方法是:
>>> sorted(set(a).intersection(xyz))
[0, 4, 6, 7, 9]
或者那些在 xyz
但不在 a
中的元素:
>>> sorted(set(xyz).difference(a))
[12, 242]
但是对于更复杂的循环,您可能希望通过迭代命名良好的 generator expression 和/或调用命名良好的函数来将其展平。试图将所有内容都放在一条线上很少是“Pythonic”。
更新以下对您的问题和接受的答案的附加评论
我不确定您要对 enumerate
做什么,但如果 a
是字典,您可能想要使用键,如下所示:
>>> a = {
... 2: 'Turtle Doves',
... 3: 'French Hens',
... 4: 'Colly Birds',
... 5: 'Gold Rings',
... 6: 'Geese-a-Laying',
... 7: 'Swans-a-Swimming',
... 8: 'Maids-a-Milking',
... 9: 'Ladies Dancing',
... 0: 'Camel Books',
... }
>>>
>>> xyz = [0, 12, 4, 6, 242, 7, 9]
>>>
>>> known_things = sorted(set(a.iterkeys()).intersection(xyz))
>>> unknown_things = sorted(set(xyz).difference(a.iterkeys()))
>>>
>>> for thing in known_things:
... print 'I know about', a[thing]
...
I know about Camel Books
I know about Colly Birds
I know about Geese-a-Laying
I know about Swans-a-Swimming
I know about Ladies Dancing
>>> print '...but...'
...but...
>>>
>>> for thing in unknown_things:
... print "I don't know what happened on the {0}th day of Christmas".format(thing)
...
I don't know what happened on the 12th day of Christmas
I don't know what happened on the 242th day of Christmas
以下是已接受答案的简化/一个衬里:
a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]
for x in (x for x in xyz if x not in a):
print(x)
12
242
请注意,generator
保持内联。这在 python2.7
和 python3.6
上进行了测试(注意 print
中的括号;))
即便如此,这确实很麻烦:x
被提及 四次 次。
我个人认为这是最漂亮的版本:
a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]
for x in filter(lambda w: w in a, xyz):
print x
编辑
如果您非常热衷于避免使用 lambda,您可以使用部分函数应用程序并使用 operator 模块(提供大多数运算符的功能)。
https://docs.python.org/2/library/operator.html#module-operator
from operator import contains
from functools import partial
print(list(filter(partial(contains, a), xyz)))
filter(a.__contains__, xyz)
。通常当人们使用 lambda 时,他们确实需要更简单的东西。
__contains__
与其他方法一样,只是它是一个特殊 方法,这意味着它可以由运算符间接调用(在本例中为 in
)。但它也可以直接调用,它是公共 API 的一部分。私有名称被明确定义为最多有一个尾随下划线,以提供特殊方法名称的例外 - 并且它们在类范围内的词法上受到名称修饰的影响。请参阅 docs.python.org/3/reference/datamodel.html#specialnames 和 docs.python.org/3.6/tutorial/classes.html#private-variables 。
in
是单独分派 wrt 右操作数)。此外,请注意 operator
还以 __contains__
名称导出 contains
方法,因此它肯定不是私有名称。我认为您只需要学会接受并非每个双下划线都意味着“远离”的事实。 :-]
lambda
需要修复以包含 not
:lambda w: not w in a, xyz
我可能会使用:
for x in xyz:
if x not in a:
print(x...)
pythonic
结果。我可以用我使用的所有其他语言(scala、kotlin、javascript、R、swift、..)进行功能性编码,但在 python 中困难/尴尬
a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]
set(a) & set(xyz)
set([0, 9, 4, 6, 7])
import time a = [2,3,4,5,6,7,8,9,0] xyz = [0,12,4,6,242,7,9] start = time.time() print (set(a) & set(xyz)) print time.time() - start
if x in ignore: ...
。
if set(a) - set(ignore) == set([]):
进行比较,所以也许这就是它比检查成员资格要慢得多的原因。我以后会在一个比我写的更简单的例子上再次测试这个。
如果生成器表达式过于复杂或过于复杂,您也可以使用 generators:
def gen():
for x in xyz:
if x in a:
yield x
for x in gen():
print x
我喜欢 Alex's answer,因为 filter 正是应用于列表的 if,所以如果您想在给定条件的情况下探索列表的子集,这似乎做最自然的方式
mylist = [1,2,3,4,5]
another_list = [2,3,4]
wanted = lambda x:x in another_list
for x in filter(wanted, mylist):
print(x)
这种方法对于关注点分离很有用,如果条件函数发生变化,唯一需要摆弄的代码就是函数本身
mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
for x in filter(wanted, mylist):
print(x)
当您不想要列表成员时,生成器方法似乎更好,但是对所述成员进行修改,这似乎更适合生成器
mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
generator = (x**0.5 for x in mylist if wanted(x))
for x in generator:
print(x)
此外,过滤器与生成器一起使用,尽管在这种情况下它效率不高
mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
generator = (x**0.9 for x in mylist)
for x in filter(wanted, generator):
print(x)
但是,当然,这样写还是不错的:
mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
# for x in filter(wanted, mylist):
for x in mylist if wanted(x):
print(x)
使用 intersection
或 intersection_update
交点:a = [2,3,4,5,6,7,8,9,0] xyz = [0,12,4,6,242,7,9] ans = sorted(set(a).intersection(set (xyz)))
intersection_update: a = [2,3,4,5,6,7,8,9,0] xyz = [0,12,4,6,242,7,9] b = set(a) b.intersection_update(xyz)那么 b 就是你的答案
查找列表 a 和 b 的唯一共同元素的简单方法:
a = [1,2,3]
b = [3,6,2]
for both in set(a) & set(b):
print(both)
基于这里的文章:https://towardsdatascience.com/a-comprehensive-hands-on-guide-to-transfer-learning-with-real-world-applications-in-deep-learning-212bf3b2f27a我出于同样的原因使用了以下代码,它工作得很好:
an_array = [x for x in xyz if x not in a]
这条线是程序的一部分!这意味着 XYZ 是一个要预先定义和分配的数组,也是变量 a
使用生成器表达式(在所选答案中推荐)会带来一些困难,因为结果不是数组
gen = (y for (x,y) in enumerate(xyz) if x not in a)
返回 >>>12
当我输入for x in gen: print x
时——那么为什么会出现 enumerate 的意外行为?for x in xyz if x:
for x in (x for x in xyz if x not in a):
对我有用,但为什么你不应该只做for x in xyz if x not in a:
,我不确定...