Python列表推导式、解包和多个操作

41
我希望解包我通过以下方式创建的元组,以便结果只是一个简单的列表。我可以用2-3行代码得到所需的结果,但肯定有一种更简洁的列表推导式吧?
>>> x = range(10)
>>> y = [(i,j**2) for i,j in zip(x,x)]
>>> y
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)]

我想要的是 result = [0,0,1,1,2,4,3,9.....]

进行中

y = len(x)*[0]
y[::2] = x
y[1::2] = [i**2 for i in x]

这可以满足我的需求,但如果我需要更一般的情况怎么办:

y = [(i, sqrt(i), i**3, some_operation_on_i, f(i), g(i)) for i in x]

比如我想得到一个直接的结果列表,其中我只指定了一个操作(平方),以便在每个i后面跟随任意数量的操作。


你真的想要将元组列表展开成一个平面列表。 - smci
2个回答

65

使用嵌套列表推导:

result = [a for tup in y for a in tup]

例子:

>>> x = range(10)
>>> y = [(i,j**2) for i,j in zip(x,x)]
>>> [a for tup in y for a in tup]
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

这对于您的更一般情况也能很好地发挥作用,或者您可以在一个步骤中完成所有操作:

y = [a for i in x for a in (i, sqrt(i), i**3, some_operation_on_i, f(i), g(i))]

如果嵌套的列表推导式看起来有些奇怪,这是它作为普通 for 循环的样子:

y = []
for i in x:
    for a in (i, sqrt(i), i**3, some_operation_on_i, f(i), g(i)):
        y.append(a)

这个一行代码的解决方案太棒了。我折腾了好一阵子,直到看到这篇文章,才发现我嵌套的for循环顺序是错误的... - Robert

28

鉴于

>>> import itertools
>>> x = range(3)
>>> y = [(i, j**2) for i, j in zip(x, x)]
>>> y
[(0, 0), (1, 1), (2, 4)]
你可以使用 itertools.chain.from_iterable:
>>> list(itertools.chain.from_iterable(y))
[0, 0, 1, 1, 2, 4]
为了跳过中间的y
>>> list(itertools.chain.from_iterable((i, j**2) for i, j in zip(x, x)))
[0, 0, 1, 1, 2, 4]

3
为什么不直接使用itertools.chain.from_iterable(y) - Dev Aggarwal
@DevAggarwal:说得好,这个功能从Python 2.6版本就已经可用了。 - Tim Pietzcker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接