条件for循环的函数

时间:2012-04-01 10:17:44

标签: python loops conditional

好的,这是我正在使用的完整代码。现在我提供了输入和输出。希望早些时候我的荒谬问题更有意义......

def get_positions(xs, item):    
    if isinstance(xs, list):
        for i, it in enumerate(xs):
            for pos in get_positions(it, item):
                yield (i,) + pos
    elif xs == item:
        yield ()
blocks = [-12,-10,-8,-6,-4,-2,0,2,4,6,8,10,12,14,16]
startcombos = [[-12], [-12, -10], [-12, -10, -8], [-12, -10, -8, -6], [-12, -10, -8, -6, -4], [-12, -10,-8, -6, -4, -2], [-12, -10, -8, -6, -4, -2, 0], [-12, -10, -8, -6, -4, -2, 0, 2], [-12, -10, -8, -6, -4, -2, 0, 2, 4], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14], [-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16]]
combos = [[-10], [-10, -8], [-10, -8, -6], [-10, -8, -6, -4], [-10, -8, -6, -4, -2], [-10, -8, -6,-4, -2, 0], [-10, -8, -6, -4, -2, 0, 2], [-10, -8, -6, -4, -2, 0, 2, 4], [-10, -8, -6, -4, -2, 0, 2, 4, 6], [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8], [-10, -8, -6, -4, -2, 0, 2, 4, 6,8, 10], [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12], [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14], [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16], [-8], [-8, -6], [-8, -6, -4], [-8, -6, -4, -2], [-8, -6, -4, -2, 0], [-8, -6, -4, -2, 0, 2], [-8, -6, -4, -2, 0, 2, 4], [-8, -6, -4, -2, 0, 2, 4, 6], [-8, -6, -4, -2, 0, 2, 4, 6, 8], [-8, -6, -4, -2, 0, 2, 4, 6, 8, 10], [-8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12], [-8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14], [-8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16], [-6], [-6, -4], [-6, -4, -2], [-6, -4, -2, 0], [-6, -4, -2, 0, 2], [-6, -4, -2, 0, 2, 4], [-6, -4, -2, 0, 2, 4, 6], [-6, -4, -2, 0, 2, 4, 6, 8], [-6, -4, -2, 0, 2, 4, 6, 8, 10], [-6, -4, -2, 0, 2, 4, 6, 8, 10, 12], [-6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14], [-6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16], [-4], [-4, -2], [-4, -2, 0], [-4, -2, 0, 2], [-4, -2, 0, 2, 4], [-4, -2, 0, 2, 4, 6],[-4, -2, 0, 2, 4, 6, 8], [-4, -2, 0, 2, 4, 6, 8, 10], [-4, -2, 0, 2, 4, 6, 8, 10, 12], [-4, -2, 0, 2, 4, 6, 8, 10, 12, 14], [-4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16], [-2], [-2, 0],[-2, 0, 2], [-2, 0, 2, 4], [-2, 0, 2, 4, 6], [-2, 0, 2, 4, 6, 8], [-2, 0, 2, 4, 6, 8, 10], [-2, 0, 2, 4, 6, 8, 10, 12], [-2, 0, 2, 4, 6, 8, 10, 12, 14], [-2, 0, 2, 4, 6, 8, 10, 12, 14, 16], [0], [0, 2], [0, 2, 4], [0, 2, 4, 6], [0, 2, 4, 6, 8], [0, 2, 4, 6, 8, 10], [0,2, 4, 6, 8, 10, 12], [0, 2, 4, 6, 8, 10, 12, 14], [0, 2, 4, 6, 8, 10, 12, 14, 16], [2], [2, 4], [2, 4, 6], [2, 4, 6, 8], [2, 4, 6, 8, 10], [2, 4, 6, 8, 10, 12], [2, 4, 6, 8, 10, 12, 14], [2, 4, 6, 8, 10, 12, 14, 16], [4], [4, 6], [4, 6, 8], [4, 6, 8, 10], [4, 6, 8, 10,12], [4, 6, 8, 10, 12, 14], [4, 6, 8, 10, 12, 14, 16], [6], [6, 8], [6, 8, 10], [6, 8, 10, 12], [6, 8, 10, 12, 14], [6, 8, 10, 12, 14, 16], [8], [8, 10], [8, 10, 12], [8, 10, 12, 14], [8, 10, 12, 14, 16], [10], [10, 12], [10, 12, 14], [10, 12, 14, 16], [12], [12, 14], [12, 14, 16], [14], [14, 16], [16]]

temp = []
for i in range(len(startcombos)):   
    for j in list(get_positions(combos,startcombos[i][-1]+2)):
        if j[-1]==0 and combos[j[0]][-1]!=blocks[-1]:

            for k in list(get_positions(combos,combos[j[0]][-1]+2)):                
                if k[-1]==0 and combos[k[0]][-1]!=blocks[-1]:

                    for l in list(get_positions(combos,combos[k[0]][-1]+2)):
                        if l[-1]==0 and combos[l[0]][-1]==blocks[-1]:
                            temp.append(tuple(startcombos[i]))
                            temp.append(tuple(combos[j[0]]))
                            temp.append(tuple(combos[k[0]]))
                            temp.append(tuple(combos[l[0]]))
                            combinations.append(temp)
                            temp = []

这是一个生成长度为4的temp的代码。如果组合的长度增加,我会在更大的循环中包含另一个条件,如下所示

for i in range(len(startcombos)):   
    for j in list(get_positions(combos,startcombos[i][-1]+2)):
        if j[-1]==0 and combos[j[0]][-1]!=blocks[-1]:

            for k in list(get_positions(combos,combos[j[0]][-1]+2)):                
                if k[-1]==0 and combos[k[0]][-1]!=blocks[-1]:               

                    for l in list(get_positions(combos,combos[k[0]][-1]+2)):
                        if l[-1]==0 and combos[l[0]][-1]!=blocks[-1]:

                            for m in list(get_positions(combos,combos[l[0]][-1]+2)):
                                if m[-1]==0 and combos[m[0]][-1]==blocks[-1]:
                                    temp.append(tuple(startcombos[i]))
                                    temp.append(tuple(combos[j[0]]))
                                    temp.append(tuple(combos[k[0]]))
                                    temp.append(tuple(combos[l[0]]))
                                    temp.append(tuple(combos[m[0]]))                                        
                                    combinations.append(temp)
                                    temp = []

这将生成长度为5的临时值。正如您已注意到第一个和最后一个条件和循环更改,中间部分保持不变。如何编写一个函数或任何其他方法,我可以用可变长度来实现它?

现在我得到的基本上是通过提供特定条件获得的组合。我知道我可以尝试使用itertools的python组合,但如果我想要特定的组合,那么生成所有组合根本不值得,除了计算时间也很重要。因此,它将为长度4提供以下输出

combinations[0] = [[-12],[-10],[-8],[-6,-4,-2,0,2,4,6,8,10,12,14,16]]

等等,其中364个。

对于长度为5,它将总共提供1001种组合,其中第一种是

combinations[0] = [[-12],[-10],[-8],[-6],[-4,-2,0,2,4,6,8,10,12,14,16]]

1 个答案:

答案 0 :(得分:2)

我不完全确定我是否正确解释了你的问题;然而,接下来是一个相当普遍的练习,无论是哪种方式都应该能够启发你。出于讨论的目的,我假设您的目标是执行任意数量的嵌套for循环。

首先,让我满足Pythonistas读这个,说Pythonic这样做的方法可能涉及使用函数itertools.product和可能内置的filter()函数。

除此之外,我认为你应该熟悉递归的概念,因为它允许你“天真地”对这类问题提出简单的解决方案,而不必依赖于像Python这样的甜蜜语言为你提供了一个充满生成器功能的强大库。

假设您在某些列表列表中有一些列表,例如:

nested = [[a1, a2, a3, ..., ana],
          [b1, b2, b3, ..., bnb],
          ...
          [x1, x2, x3, ..., xnx]]

并且您希望通过包含每个列表中的单个元素的序列迭代伪词法,例如:

a1 b1 c1 ... x1
a1 b1 c1 ... x2
...
a2 b1 c1 ... x1
a2 b1 c1 ... x2
...
...
ana bnb cnc ... x(nx - 1)
ana bnb cnc ... xnx

使用普通的静态for循环很难做到这一点,因为你通常必须输出每个,对吗?你如何键入一些可变数量的for循环?一种天真的技巧是使用递归(同样这不是最恐怖的方式)。

递归说,“好吧,我有一个问题。这个问题基本上只是用我的部分数据做一些小事,然后 递归 解决同样的问题其余的数据。当我没有更多的数据可用时,我可能已经完成了这个子问题。“

一个简单,经典的递归示例是计算数字列表的总和:

def sum_nums(nums):
    # The "base case" is usually checked first. This is when your
    # recursion has run out of things to do, it just returns a simple value.
    if nums == []:
        return 0
    # The "recursive case" is the real meat and potatoes of recursion.
    # It says to take the first number and add it to the sum_nums of the
    # rest of the numbers in the list (which may be empty, hence the base case!).
    else:
        return nums[0] + sum_nums(nums[1:])

想一想。明白它。冥想它,忘记你理解它。做一些迷幻药,再考虑一下。能够在飞行中从你的屁股中拉出递归的黑客是非常重要的。

现在更先进的技术是在递归函数中传递值。在这种情况下,它可能很有用,因为在您了解基本情况之前,您不想做任何事情。如果你愿意的话,我已经遗漏了你自己实施的基础案例。

def print_lexo_lists(items, lists):
    if lists == []:
        # What do you want to do if you've taken a single item from each of your
        # lists and put it in the list called "items"?
    else:
        # Take each item from the current level and pass it down in turn to the
        # next deeper level, adding it to the running list of "items". Remove
        # the current level from the list of "lists" before passing it down.
        # In this way you're "using up" the current level, and the "lists"
        # structure is getting smaller at each level of recursive depth, until
        # you reach the base case (when it is an empty list)
        for current_item in lists[0]:
            print_lexo_lists(items + [current_item], lists[1:])

希望你能在某种程度上遵循这一点。我强烈建议您在尝试以下方法之前实现它,这实际上是通过生成 笛卡尔积来在Python中执行超级嵌套for循环的正确方式> 列表:

from itertools import product
for items in product(*lists):
    print ' '.join(items)