我正在编写一个python脚本,其中我有多个for循环,除了嵌套在它们中的for循环数之外,它们都是相同的。
让我告诉你我的意思:
#4 & 1
for a1 in someList:
for a2 in someList:
for a3 in someList:
for a4 in someList:
for b1 in anotherList:
resultList.append((a1 + a2 + a3 + a4) - b1);
#3 & 1
for a1 in someList:
for a2 in someList:
for a3 in someList:
for b1 in anotherList:
resultList.append((a1 + a2 + a3) - b1);
#2 & 1
for a1 in someList:
for a2 in someList:
for b1 in anotherList:
resultList.append((a1 + a2) - b1);
#2 & 2
for a1 in someList:
for a2 in someList:
for b1 in anotherList:
for b2 in anotherList:
resultList.append((a1 + a2) - (b1 + b2));
请记住,这只是一个展示问题的示例。我使用的实际数据不是数字,我每次迭代都会执行更多操作。
好的,现在问题是:
如何将所有这些代码放入一个很好的函数中,以便我可以做这样的事情:
myFunc(4, 1);
myFunc(3, 1);
myFunc(2, 1);
myFunc(2, 2);
如果你们能回答这个问题,这对我来说将是一个巨大的帮助。我没有足够的创造力来自己解决这个难题。 :(
另外,如果答案已经存在,很抱歉发布这个问题 - 我不知道这个东西叫什么,所以我不知道要搜索什么。
提前致谢! 〜PM
更新: 谢谢大家的帮助。我认为这会奏效。你们都非常有帮助!
答案 0 :(得分:3)
没问题。作为一个建议,如此多的嵌套for循环是糟糕的风格,甚至可以让你的代码难以理解!你应该避免超过两个循环。如果其他东西需要一个循环,你可以为它编写一个函数。
itertools
(https://docs.python.org/3/library/itertools.html#itertools.product)中实际上有一个函数可以执行您正在寻找的内容,称为product()
。 product
将为您提供类似迭代的笛卡尔积,例如,如果someList = [1, 2, 3 ... n]
,则product(someList, 2)
将为您提供[(1, 1), (1, 2), (1, 3) ... (1, n), (2, 1) ... (n, 1) ... (n, n)]
。您可以更改列表重复的次数。同样为someList
和someOtherList
执行此操作
def func(num_a, num_b):
a_sums = sum(a_inner for a_inner in product(someList, repeat=num_a))
b_sums = sum(b_inner for b_inner in product(someOtherList, repeat=num_b))
return (a - b for a, b in product(a_sums, b_sums))
此函数将生成第一个列表中笛卡尔积的总和的可迭代,然后对其他列表执行相同操作。请记住,您可能希望能够将列表作为参数传递,而不是将它们视为一些非局部变量。
答案 1 :(得分:2)
我的方法是首先否定您的b
列表。这样,你可以使用类似的东西:
from itertools import product
def sum_of_cartesian_tuples(*lists):
tuples = product(*lists)
return map(sum, tuples)
if __name__ == '__main__':
a1 = [1,2,3]
a2 = [3,4,5]
b1 = [6,7,8]
b1_neg = [-1*b for b in b1]
print sum_of_cartesian_tuples(a1, a2, b1_neg)
# [-2, -3, -4, -1, -2, ..., 0, -1, 2, 1, 0]
请注意,此代码在Python 2.7中,尚未在Python 3.X中进行过测试。但是,实质上,你的循环遍历列表生成的笛卡尔积中的元组,因此使用itertools.product
可以节省所有循环。
答案 2 :(得分:1)
您可以使用itertools生成笛卡尔积:
import itertools
> a = [1,2]
> b = [3,4]
> c = [4,5]
> itertools.product(a, b, c)
[(1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (2, 2, 4), (2, 2, 5), (2, 3, 4), (2, 3, 5)]
您可以使用循环或列表理解生成列表列表:
> list1 = [1,2,3]
> list2 = [3,4,5]
> a, b = 4, 1
> [list1 for i in range(a)] + [list2 for i in range(b)]
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [2, 3, 4]]
然后使用笛卡尔积:
> lists = [list1 for i in range(a)] + [list2 for i in range(b)]
> itertools.product(*lists)
您可以添加一个功能来处理每个子列表:
def doWorkOnProduct(list1, list2, a, b, func):
lists = [list1 for i in range(a)] + [list2 for i in range(b)]
products = itertools.product(*lists)
return map(func, products)
示例电话:
def func(nums):
return sum(nums[:-1]) + nums[-1]
> sums = list(doWorkOnProduct([1,2,3], [4,5,6], 4, 1, func))
> print sum(sums)
> 3159