使用列表理解来构建元组


70

如何使用列表推导从列表构建2元组的元组。相当于

tup = ()
for element in alist:
    tup = tup + ((element.foo, element.bar),)

Answers:


99
tup = tuple((element.foo, element.bar) for element in alist)

从技术上讲,它是一个生成器表达式。就像列表理解一样,但是它的计算是延迟的,不需要为中间列表分配内存。

为了完整起见,列表理解应如下所示:

tup = tuple([(element.foo, element.bar) for element in alist])

 

PS:attrgetter速度不快(alist此处有一百万个项目):

In [37]: %timeit tuple([(element.foo, element.bar) for element in alist])
1 loops, best of 3: 165 ms per loop

In [38]: %timeit tuple((element.foo, element.bar) for element in alist)
10 loops, best of 3: 155 ms per loop

In [39]: %timeit tuple(map(operator.attrgetter('foo','bar'), alist))
1 loops, best of 3: 283 ms per loop

In [40]: getter = operator.attrgetter('foo','bar')

In [41]: %timeit tuple(map(getter, alist))
1 loops, best of 3: 284 ms per loop

In [46]: %timeit tuple(imap(getter, alist))
1 loops, best of 3: 264 ms per loop

1
(+1)可能值得指出,从技术上讲,这不是列表理解(但我敢肯定OP不会介意的:))
— NPE

3
你也可以tuple(map(operator.attrgetter('foo','bar'),alist))。我可能会使用您发布的内容以提高可读性,但attrgetter可能会有一点性能优势。您必须timeit查看它是否处于真正的紧密循环中。
— mgilson

2
由于在此示例中调用了tuple(),因此列表理解和生成器表达式之间有什么区别?不管形式如何,它都不会占用相同的内存空间吗?
— 2013年

1
将生成器表达式传递给元组构造函数具有评估整个生成器表达式的作用,并且使用与列表推导相同的内存。列表理解在我的计算机上的运行速度提高了约20%。我可以看到生成器的好处,如果一个接一个地使用这些术语,但是在传递给元组构造函数时看不到任何好处。
— 2013年

2
@EricRoper不,它使用内存的两倍。首先,它使用生成器的所有元素来构建列表,然后从列表中创建一个元组。那时,生成器生成了元素的“集合”的两个副本,并且仅在一段时间之后才对列表进行垃圾收集。如果生成器很大,那么即使是一条指令,您也可能无法同时将列表和元组保留在内存中。预计attrgetter的速度会降低,因为您正在用函数调用加属性查找替换属性查找。
— Bakuriu

0

您可以使用以下表达式

tup = *[(element.foo, element.bar) for element in alist]

这首先将生成一个元组列表,然后将该元组列表转换为元组的元组。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.