Python如何将嵌套的循环放入函数中?

时间:2016-01-29 23:36:37

标签: python loops for-loop nested

我正在编写一个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

更新: 谢谢大家的帮助。我认为这会奏效。你们都非常有帮助!

3 个答案:

答案 0 :(得分:3)

没问题。作为一个建议,如此多的嵌套for循环是糟糕的风格,甚至可以让你的代码难以理解!你应该避免超过两个循环。如果其他东西需要一个循环,你可以为它编写一个函数。

itertoolshttps://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)]。您可以更改列表重复的次数。同样为someListsomeOtherList执行此操作

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