【问题标题】:Python How Can I Put Nested For Loops Into a Function?Python如何将嵌套的for循环放入函数中?
【发布时间】:2016-05-07 20:49:57
【问题描述】:

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

如果你们能回答这个问题,这对我来说将是一个巨大的帮助。我没有足够的创造力来独自解决这个难题。 :(

另外,如果答案已经存在,很抱歉发布这个问题 - 我不知道这个东西叫什么,所以我不知道要搜索什么。

提前致谢! ~下午

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

【问题讨论】:

  • 为什么会有这些五重嵌套的for 循环?听起来你在暴力破解你真的不应该做的事情,要么是因为有更快的方法可以做到这一点,要么是因为这是一个非常困难的问题,你应该引入一个已建立的库。

标签: python loops for-loop nested


【解决方案1】:

没问题。作为一个忠告,这么多嵌套的 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)]。您可以改变列表重复的次数。对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))

此函数将生成第一个列表的笛卡尔积总和的可迭代对象,然后对另一个列表执行相同操作。请记住,您可能希望能够将列表作为参数传递,而不是将它们视为一些非局部变量。

【讨论】:

  • 您不能将repeat 参数按位置传递给itertools.product。通过关键字参数传递它。
  • 感谢您指出这一点。我应该更谨慎地编写代码。编辑修复它。
  • 嘿,我还有一个问题要问你。如果一对中的两个值都不同,我如何只在结果列表中包含一个笛卡尔对?例如,我永远不会有[a, a],但[a, b] 会起作用。谢谢!
【解决方案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 可以节省所有循环。

【讨论】:

  • 成对?除此之外,这个答案很好,但是你为什么一直调用元组对呢?即使在您的示例中,它们每个也有 3 个元素。
  • 如果我也在迭代非数字值,此方法是否有效?
  • @PMethodVanAlternate: itertools.product 可以正常工作。 sum 当然可能不会,但你可能会用你的非数字值做其他事情。
  • 我修正了对的措辞。这取决于什么样的非数字值。但是,您想要的本质在于产品的使用。
【解决方案3】:

您可以使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    • 2015-12-22
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多