【问题标题】:python list comprehension to produce two values in one iterationpython列表理解在一次迭代中产生两个值
【发布时间】:2013-05-11 18:53:38
【问题描述】:

我想在python中生成一个列表如下-

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....]

你会发现,这不过是n, n*n

我尝试在 python 中编写这样的列表理解如下 -

lst_gen = [i, i*i for i in range(1, 10)]

但是这样做会产生语法错误。

通过列表理解生成上述列表的好方法是什么?

【问题讨论】:

    标签: python list list-comprehension


    【解决方案1】:

    使用itertools.chain.from_iterable:

    >>> from itertools import chain
    >>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6)))
    [1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
    

    或者你也可以使用generator函数:

    >>> def solve(n):
    ...     for i in xrange(1,n+1):
    ...         yield i
    ...         yield i**2
    
    >>> list(solve(5))
    [1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
    

    【讨论】:

      【解决方案2】:

      这个问题很老,但只是为了好奇的读者,我提出了另一种可能性: 如第一篇文章所述,您可以轻松地从数字列表中创建一对 (i, i**2)。然后你想把这对夫妇弄平。因此,只需在您的理解中添加 flatten 操作即可。

      [x for i in range(1, 10) for x in (i,i**2)]
      

      【讨论】:

      • 这是我在查找问题之前头脑中最有希望的解决方案,它知道这是我为该问题选择的解决方案。 -- 除了我实际上会使用一个循环和append。
      【解决方案3】:

      一个鲜为人知的技巧:列表推导式可以有多个 for 子句。

      例如:

      >>> [10*x+y for x in range(4) for y in range(3)]
      [0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]
      

      在您的特定情况下,您可以这样做:

      >>> [x*x if y else x for x in range(5) for y in range(2)]
      [0, 0, 1, 1, 2, 4, 3, 9, 4, 16]
      

      【讨论】:

        【解决方案4】:

        列表推导一次生成 一个 元素。相反,您的选择是将循环更改为一次仅生成一个值:

        [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
        

        或生成元组,然后使用itertools.chain.from_iterable() 展平列表:

        from itertools import chain
        
        list(chain.from_iterable((i, i*i) for i in range(1, 10)))
        

        输出:

        >>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
        [1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
        >>> list(chain.from_iterable((i, i*i) for i in range(1, 10)))
        [1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
        

        【讨论】:

        • 我不知道我应该对第一个解决方案着迷还是厌恶
        【解决方案5】:
        lst_gen = sum([(i, i*i) for i in range(1, 10)],())
        

        哦,我应该提到总和可能违反了一次迭代规则:(

        【讨论】:

        • 虽然这行得通,但以这种方式使用sum 会产生二次性能,因此是一个有点危险的习惯。
        • 是的,itertools 会更好,但有时我有点喜欢求和技巧:P
        • @DSM,请原谅我的无知,为什么将sum() 与(元组的)列表理解一起使用会产生二次性能?我的部分问题是,“这种方式”的哪个方面有问题?
        【解决方案6】:

        您可以创建一个列表列表,然后使用 reduce 加入它们。

        print [[n,n*n] for n in range (10)]
        

        [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49 ], [8, 64], [9, 81]]

        print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)])
        

        [0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

         print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\
         for n in range (1,10)])
        

        [1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343, 8, 64, 512、9、81、729]

        Reduce 接受一个可调用表达式,该表达式接受两个参数并从前两项开始处理一个序列。最后一个表达式的结果然后用作后续调用中的第一项。在这种情况下,每个列表一个接一个地添加到列表列表中的第一个列表,然后返回该列表作为结果。

        列表推导使用“for var in 序列”表达式定义的变量和序列隐式调用带有 lambda 表达式的 map。以下是同样的事情。

        map(lambda n:[n,n*n],range(1,10))
        

        [[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64 ], [9, 81]]

        我不知道有一个更自然的 Python 表达式来表示 reduce。

        【讨论】:

          【解决方案7】:

          另一种选择,对某些人来说可能看起来不正常

          >>> from itertools import izip, tee
          >>> g = xrange(1, 11)
          >>> x, y = tee(g)
          >>> y = (i**2 for i in y)
          >>> z = izip(x, y)
          >>> output = []
          >>> for k in z:
          ...     output.extend(k)
          ... 
          >>> print output
          [1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100]
          

          【讨论】:

            【解决方案8】:

            另一种选择:

            reduce(lambda x,y: x + [y, y*y], range(1,10), [])
            

            【讨论】:

            • 这需要在 Python 3 中导入。(functools)
            【解决方案9】:
            >>> lst_gen = [[i, i*i] for i in range(1, 10)]
            >>> 
            >>> lst_gen
            [[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
            >>> 
            >>> [num for elem in lst_gen for num in elem]
            [1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
            

            这是我的参考 http://docs.python.org/2/tutorial/datastructures.html

            【讨论】:

              【解决方案10】:

              这个线程中有很多技巧。这是另一个使用没有导入的单列生成器

              x = (lamdba : [[(yield i), (yield i**2)] for i in range(10)])()
              

              编辑: 这将引发 Python 3.7 中的 DeprecatedWarning 和 Python 3.8 中的 SyntaxError: https://docs.python.org/dev/whatsnew/3.7.html#deprecated-python-behavior

              【讨论】:

                【解决方案11】:

                一个简单的可能是:

                [i ** j for i in range(1, 6) for j in [1, 2]]
                

                这对于任务以及列表 comp 替换两个嵌套循环的事实非常明确(而正如其他答案所示,可以说是可以展平的)。 输出:

                [1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
                

                【讨论】:

                  【解决方案12】:

                  如前所述,itertools 是要走的路。这是我的做法,我觉得更清楚:

                  [i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])]
                  

                  【讨论】:

                    【解决方案13】:

                    试试这两个班轮

                    lst = [[i, i*i] for i in range(10)]
                    [lst.extend(i) for i in lst]
                    

                    根据需要更改数学。

                    更好

                    #Change my_range to be the number you want range() function of
                    start = 1
                    my_range = 10
                    lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)]
                    

                    【讨论】:

                      猜你喜欢
                      • 2013-05-23
                      • 2021-10-05
                      • 1970-01-01
                      • 2016-06-07
                      • 2017-12-09
                      • 2019-11-28
                      • 2014-02-15
                      • 2020-12-03
                      相关资源
                      最近更新 更多