[英]Find cartesian product of lists filtering out the elements based on condition
I recently came across this notation 我最近遇到了这种表示法
a = [1,2,3,4]
b = [2,4,6]
c = [(x,y,z) for x in a for y in b for z in a]
First I don't know how to search for the notation in creating c
, is there a name for this type of structure? 首先,我不知道如何在创建
c
搜索表示法,这种结构是否有名称?
Also, I'm confident that c
can be updated to not allow x
to equal z
. 另外,我有信心可以将
c
更新为不允许x
等于z
。 Please can you help me with this? 请你能帮我吗?
I've tried various things on the lines of 我已经尝试过各种方法
c = [(x,y,z) for x in a for y in b for z in a for x != z]
but so far I can't find anything that works, or is even valid syntax. 但是到目前为止,我找不到任何有效的语法。
What I'm trying to accomplish is to find every combination of (a,b,a)
where a
can only be used once in each line so the result would be 我要完成的工作是找到
(a,b,a)
每种组合,其中a
只能在每一行中使用一次,因此结果是
[(1, 2, 2),
(1, 2, 3),
(1, 2, 4),
(1, 4, 2),
(1, 4, 3),
(1, 4, 4),
(1, 6, 2),
(1, 6, 3),
(1, 6, 4),
(2, 2, 1),
(2, 2, 3),
(2, 2, 4),
(2, 4, 1),
(2, 4, 3),
(2, 4, 4),
(2, 6, 1),
(2, 6, 3),
(2, 6, 4),
(3, 2, 1),
(3, 2, 2),
(3, 2, 4),
(3, 4, 1),
(3, 4, 2),
(3, 4, 4),
(3, 6, 1),
(3, 6, 2),
(3, 6, 4),
(4, 2, 1),
(4, 2, 2),
(4, 2, 3),
(4, 4, 1),
(4, 4, 2),
(4, 4, 3),
(4, 6, 1),
(4, 6, 2),
(4, 6, 3)]
Thanks 谢谢
It is known as list comprehension and you can use logical if
within it to filter the results in the returned list as: 它被称为列表理解 ,你可以使用逻辑
if
内它来过滤返回列表中的结果:
>>> a = [1,2,3,4]
>>> b = [2,4,6]
# if condition to skip results where `x` equals `z` v
>>> c = [(x,y,z) for x in a for y in b for z in a if x != z]
>>> c
[(1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 4, 2), (1, 4, 3), (1, 4, 4), (1, 6, 2), (1, 6, 3), (1, 6, 4), (2, 2, 1), (2, 2, 3), (2, 2, 4), (2, 4, 1), (2, 4, 3), (2, 4, 4), (2, 6, 1), (2, 6, 3), (2, 6, 4), (3, 2, 1), (3, 2, 2), (3, 2, 4), (3, 4, 1), (3, 4, 2), (3, 4, 4), (3, 6, 1), (3, 6, 2), (3, 6, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 6, 1), (4, 6, 2), (4, 6, 3)]
Instead of using nested list comprehension , you may get the same behavior using itertools.product
as well: 除了使用嵌套列表
itertools.product
,您还可以使用itertools.product
获得相同的行为:
>>> from itertools import product
>>> [(x,y,z) for x, y, z in product(a, b, a) if x !=z]
[(1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 4, 2), (1, 4, 3), (1, 4, 4), (1, 6, 2), (1, 6, 3), (1, 6, 4), (2, 2, 1), (2, 2, 3), (2, 2, 4), (2, 4, 1), (2, 4, 3), (2, 4, 4), (2, 6, 1), (2, 6, 3), (2, 6, 4), (3, 2, 1), (3, 2, 2), (3, 2, 4), (3, 4, 1), (3, 4, 2), (3, 4, 4), (3, 6, 1), (3, 6, 2), (3, 6, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 6, 1), (4, 6, 2), (4, 6, 3)]
this is list comprehension
and the correct syntax for the filtering condition is this: 这是
list comprehension
并且过滤条件的正确语法是:
c = [(x,y,z) for x in a for y in b for z in a if x != z]
The syntax being used to create c
is called a list comprehension . 用于创建
c
的语法称为列表理解 。 Almost your exact case is the fourth code example in those docs: 几乎您的确切情况是这些文档中的第四个代码示例:
A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses.
列表推导由包含表达式的方括号组成,后跟一个for子句,然后是零个或多个for或if子句。 The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it.
结果将是一个新列表,该列表是通过在其后的for和if子句的上下文中评估表达式而得出的。 For example, this listcomp combines the elements of two lists if they are not equal:
例如,如果两个列表的元素不相等,则此listcomp组合它们:
>>>[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
>>> [[(x,y)对于[1,2,3]中的x对于[3,1,4]中的y如果x!= y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
[(1、3),(1、4),(2、3),(2、1),(2、4),(3、1),(3、4)]
All you need to do is change your last for
to an if
: 您需要做的就是将最后一个更改
for
if
:
c = [(x,y,z) for x in a for y in b for z in a if x != z]
Just for the sake of variety, I would like to add the following solution that is based on itertools.product
and circumvents the if
check. 仅出于多样性的考虑,我想添加以下基于
itertools.product
解决方案,它绕过了if
检查。
from itertools import product
a = [1,2,3,4]
b = [2,4,6]
c = []
for i, item in enumerate(a):
c.extend((item, x, y) for x, y in product(b, a[:i] + a[i+1:]))
print(c)
producing: 生产:
[(1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 4, 2), (1, 4, 3), (1, 4, 4), (1, 6, 2), (1, 6, 3), (1, 6, 4), (2, 2, 1), (2, 2, 3), (2, 2, 4), (2, 4, 1), (2, 4, 3), (2, 4, 4), (2, 6, 1), (2, 6, 3), (2, 6, 4), (3, 2, 1), (3, 2, 2), (3, 2, 4), (3, 4, 1), (3, 4, 2), (3, 4, 4), (3, 6, 1), (3, 6, 2), (3, 6, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 6, 1), (4, 6, 2), (4, 6, 3)]
I did some timings too to compare the different approaches using: 我也做了一些时间比较使用以下不同的方法:
from timeit import timeit
setup = '''
from itertools import product
def list_comp(a, b):
return [(x,y,z) for x in a for y in b for z in a if x != z]
def itertools_listComp(a, b):
return [(x,y,z) for x, y, z in product(a, b, a) if x !=z]
def itertools_forLoop(a, b):
c = []
for i, item in enumerate(a):
c.extend((item, x, y) for x, y in product(b, a[:i] + a[i + 1:]))
return c
a = [1, 2, 3, 4]
b = [2, 4, 6]
'''
print('list_comp:', timeit(stmt="list_comp(a, b)", setup=setup, number=1000))
print('itertools_forLoop:', timeit(stmt="itertools_forLoop(a, b)", setup=setup, number=1000))
print('itertools_listComp:', timeit(stmt="itertools_listComp(a, b)", setup=setup, number=1000))
and the results are: 结果是:
list_comp: 0.0050
itertools_listComp: 0.0056
itertools_forLoop: 0.0086
So it seems that the plain list comprehension is the fastest. 因此,似乎简单的列表理解是最快的。 This behavior persists with bigger
a
lists too. 这种现象在更大
a
列表中也仍然存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.