将 for 循环转换为列表理解

Convert for loops into list comprehension

我有一个循环条件,我想将其转换为列表理解。我只想学习如何将复杂的 for 循环写成一行。

num = []
for i in range(2, numRows):
    row = []
    for j in range(i - 1):
        row.append(sum(num[-1][j:j + 2]))
    num.append([1] + row + [1])

我认为 list comprehension 只能与 if else 条件一起使用。我们可以在里面写正则表达式吗?谁能告诉我是否可能?下面的代码对我不起作用。

row = []
[num.append([1] + row + [1]) row = [] [row.append(sum(num[-1][j:j + 2])) for j in range(i - 1)]for i in range(2, numRows)]

编辑:我的 Pascal 三角形初始代码

class Solution(object):
    def generate(self, numRows):
        """
        :type numRows: int
        :rtype: List[List[int]]
        if numRows = 5
               [
                     [1],
                    [1,1],
                   [1,2,1],
                  [1,3,3,1],
                 [1,4,6,4,1]
               ]
        """

        num = [[1], [1, 1]]
        if numRows == 1:
            return num[0]
        elif numRows == 2:
            return num

        row = []
        for i in range(2, numRows):
            for j in range(i - 1):
                row.append(sum(num[-1][j:j + 2]))
            num.append([1] + row + [1])
            row = []

        return num

您似乎在尝试制作帕斯卡三角。要使第一个代码块中的代码正常工作,您需要正确初始化 num

num = [[1,1]]

在列表理解中生成帕斯卡三角是不切实际的*,因为要生成每一行,您需要访问前一行。但是,结合使用 "traditional" for 循环和使用 zip 的列表组合来创建需要相加的数字对很容易。

def pascal(m):
    """ Build m rows of Pascal's triangle """
    row = [1]
    rows = [row]
    for i in xrange(m):
        #Generate next row from current row
        row = [x + y for x, y in zip([0] + row, row + [0])]
        rows.append(row)
    return rows

#test
width = 50
for row in pascal(10):
    print " ".join(["%3d" % x for x in row]).center(width)

输出

                         1                        
                       1   1                      
                     1   2   1                    
                   1   3   3   1                  
                 1   4   6   4   1                
               1   5  10  10   5   1              
             1   6  15  20  15   6   1            
           1   7  21  35  35  21   7   1          
         1   8  28  56  70  56  28   8   1        
       1   9  36  84 126 126  84  36   9   1      
     1  10  45 120 210 252 210 120  45  10   1    

我在您使用的列表补偿尝试中看到 row.append。请不要那样做。 list.append 方法 returns None,因此在列表 comp 中调用它会创建一个充满 None 的列表。当然,这是合法的 Python,并且在某些情况下,您 可能 能够以这种方式计算出所需的结果,但大多数有经验的 Python 程序员认为这是不好的练习滥用这样的列表组合。当您想要它们生成的实际列表时使用它们,而不仅仅是作为一种将 shoe-horn 一个 for 循环到一行的方法。

不要误会我的意思 - 我喜欢列表理解和生成器表达式。尽管一开始它们可能有点令人费解,但一旦您习惯了它们,它们就会简洁明了。并且列表组合比在传统的 for 循环中使用 .append 稍微更有效。然而,即使是最有经验的 Pythonista,deeply-nested/复杂的 list comps 和 gen 表达式也很难阅读。因此,不要试图在其中塞入太多内容,如果可以使代码更具可读性,请毫不犹豫地将它们分成多个阶段。


* 实际上可以使用 binomial coefficient 公式而不是加法在列表组合中生成帕斯卡三角。