据http://docs.python.org/2/library/itertools.html#itertools.product以下功能等同于使用他们的图书馆(我删除了一些东西,我不从它需要的):
def product(*args):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
pools = map(tuple, args)
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
就我而言,我通过产品功能3所列出,但我需要添加一些条件检查,所以它不会从一个列表的项目在另一个列表中混用某些项目,如果他们不符合要求。 所以我想我需要做的是转换:
result = [x+[y] for x in result for y in pool]
到“正常” FOR循环(不知道如何引用它们),所以我可以添加多个IF检查,以验证在列表中的项目是否应该被混合在一起或没有。
什么主要让我困惑的是,“X”是通过“结果”列表是空的迭代,但项目被添加到它,因为它遍历,所以我觉得这个是什么转换为我正常循环复杂。
这里是我的尝试之一:
def product(*args):
pools = map(tuple, args)
result = [[]]
for pool in pools:
for x in result:
for y in pool:
result.append(x+[y])
for prod in result:
yield tuple(prod)
任何帮助是极大的赞赏!
You're very close: the right hand side of a nested list comprehension is written in the same order that you'd write the for loops, so you've got that right. However, in the listcomp version, first the RHS of the assignment is computed and then it's bound to the name on the LHS. So
result = [x+[y] for x in result for y in pool]
needs to become
new_result = []
for x in result:
for y in pool:
new_result.append(x+[y])
result = new_result
So that you're not modifying result
as you iterate over it. If you wanted to forbid certain arrangements -- and you can write your constraint in such a way that it works for that iteration order, which fills in from left-to-right -- then you could do this:
def filtered_product(args, filter_fn):
pools = map(tuple, args)
result = [[]]
for pool in pools:
new_result = []
for x in result:
for y in pool:
new_val = x+[y]
if filter_fn(new_val):
new_result.append(x+[y])
result = new_result
print 'intermediate result:', result
for prod in result:
yield tuple(prod)
which gives
In [25]: list(filtered_product([[1,2,3], [4,5,6], [7,8,9]], lambda x: sum(x) % 3 != 2))
intermediate result: [[1], [3]]
intermediate result: [[1, 5], [1, 6], [3, 4], [3, 6]]
intermediate result: [[1, 5, 7], [1, 5, 9], [1, 6, 8], [1, 6, 9], [3, 4, 8], [3, 4, 9], [3, 6, 7], [3, 6, 9]]
Out[25]:
[(1, 5, 7),
(1, 5, 9),
(1, 6, 8),
(1, 6, 9),
(3, 4, 8),
(3, 4, 9),
(3, 6, 7),
(3, 6, 9)]
Whether or not this gives you any benefit over simply using (p for p in itertools.product(whatever) if condition(p))
will depend upon how many branches you can prune, because as you can see it constructs all the intermediate lists in memory.
该产品功能一般在减少操作,这可能是对你毫无帮助,如果你想为你去筛选结果的形式列出相乘。 相反,你应该写一个产品的函数,它列出了一个固定的数:
for x in list1:
for y in list2:
for z in list3:
if condition(x, y, z):
yield tuple(x, y, z)
需要注意的是在该行result = [x+[y] for x in result for y in pool]
result
出现了两次,但它是不相关的。 这种表达构建使用旧列表result
,然后这个新的列表分配到result
。
这可能是什么让你感到困惑。 等效的扩展版本将是:
def product(*args):
pools = map(tuple, args)
result = [[]]
for pool in pools:
tmp = []
for x in result: # note that it's the old 'result' here
for y in pool:
tmp.append(x+[y])
result = tmp
for prod in result:
yield tuple(prod)
文章来源: How do I convert Python's itertools.product library from a list comprehension to normal for loops?