Python 元组列表转换为整数列表

11

所以,我有一个列表嵌套元组的变量x=[(12,), (1,), (3,)],我想要最好的方法将其转换为只包含整数的列表x=[12, 1, 3]?你能帮忙吗?


3
请编辑您的问题,包括您尝试解决问题的步骤。谢谢。 - mechanical_meat
你的元组是否始终具有相同的形式?(n,) - Pedro del Sol
1
在Py3k中,zip(*x)[0]next(zip(*x))的另一种选择。 - JBernardo
可能是重复的问题,参考 python - get list of tuples first index? - Emipro Technologies Pvt. Ltd.
5个回答

14

您没有说明“最好”的含义,但是可以推测您的意思是“最符合Python风格”或“最易读”之类的。

F3AR3DLEGEND提供的列表推导式可能是最简单的。任何知道如何阅读列表推导式的人都会立即知道它的含义。

y = [i[0] for i in x]

然而,通常情况下你并不需要一个列表,只需要能够迭代一次的东西。如果你有十亿个元素在 x 中,建立一个包含十亿个元素的 y 只是为了逐个遍历可能是一个坏主意。因此,你可以使用生成器表达式:

y = (i[0] for i in x)

如果你更喜欢函数式编程,你可能更喜欢使用mapmap的缺点是你需要传递一个函数而不仅仅是一个表达式,这意味着你要么需要使用一个lambda函数,要么使用itemgetter
y = map(operator.itemgetter(0), x)

在Python 3中,这等同于生成器表达式;如果你想要一个列表,请将其传递给list。在Python 2中,它返回一个list;如果你想要一个迭代器,请使用itertools.imap而不是map
如果您想要一个更通用的展平解决方案,可以自己编写一个,但始终值得查看itertools以获取此类通用解决方案,实际上有一个名为flatten的配方,用于“展平一层嵌套”。因此,将其复制并粘贴到您的代码中(或pip install more-itertools),您就可以这样做:
y = flatten(x)

如果您查看flatten的实现方式,然后查看chain.from_iterable的实现方式,再查看chain的实现方式,您会注意到您可以使用内置函数编写相同的代码。但是为什么要这样做呢?flatten更易读且更明显。

最后,如果您想将通用版本简化为嵌套列表推导式(或生成器表达式),当然也可以:

y = [j for i in x for j in i]

然而,嵌套的列表推导式在编写和阅读时很容易出错。(请注意,第一个给出最简单答案的F3AR3DLEGEND也给出了一个嵌套推导式并且出错了。如果他都做不到,你确定你想尝试吗?)对于非常简单的情况,它们还好,但是我认为flatten更容易阅读。


那么你对元组解包的模式匹配有何看法? - Pavel Anossov
@PavelAnossov:这个怎么样?当你想要将一个元组解包成单独的命名变量时,这显然是完全正确的。当你有一个只想转换为单个值的元组时,它似乎不太清晰,但它并不是真正令人反感的。 - abarnert

5
y = [i[0] for i in x]

虽然如此,如果你的元组中有多个元素,你可以使用稍微复杂一些的列表推导式:

y = [i[j] for i in x for j in range(len(i))]

参考资料: 列表推导式


1
@pedro - 是的,它将始终具有一个元素。 - NullException
对于第二个问题:如果您需要展平任何序列的序列,则在 itertools 文档中有一个名为 flatten 的配方。了解这两个内容和列表推导可能是值得的。 - abarnert
1
你不应该颠倒 for 的顺序吗? - phant0m
1
另外,你为什么要迭代range(len(i))来获取索引值呢?i[j] for j in range(len(i))j for j in i完全相同。 - abarnert

2

只需按照以下步骤进行:

x = [i[0] for i in x]

解释:

>>> x=[(12,), (1,), (3,)]

>>> x
[(12,), (1,), (3,)]

>>> [i for i in x]
[(12,), (1,), (3,)]

>>> [i[0] for i in x]
[12, 1, 3]

1
这是最高效的方法:

x = [i for i, in x]

或者,等价地。
x = [i for (i,) in x]

这有点慢:
x = [i[0] for i in x]

你确定效率差异吗?在3.3.0中,使用一个包含1M元素的list进行快速测试,它们分别需要4.15ms和4.14ms - 看起来超过4ms的时间都花费在迭代列表和构建新列表上,因此没有任何更快的方法。如果将x更改为genexp,并将两个listcomps替换为馈入deque(genexp, maxlen=0)的genexp,则我得到1.36us vs. 1.32us。 - abarnert
更重要的是,你想象中有哪种情况会让任何人在意这两者哪一个更有效率呢? - abarnert
1
Python在SO上的高效趋势是从哪里来的呢?对我来说,这似乎是为了赚更多的积分而玩的花招。 - phant0m
2
@phant0m:有些人看到“最佳方式”就立刻理解为“最有效率的方式”。我不知道那些人为什么会用Python而不是C来编码。尤其是那些做出假设而不进行测试的人——难道这样的人不认为C总是最快的吗? - abarnert
我在Python 2.7上进行了测试,这不是一个假设(使用1M列表的34ms与46ms相比)。我认为这些方法的可读性非常接近,那么还有什么可以比较来选择“最佳”(没有人定义)? - Pavel Anossov
假设“最佳”意味着“最有效率”,几乎从来都不是一个好主意。你能想象出任何情况吗,在这种情况下,30%的改进会有所作为,但过度列表构建所涉及的4000倍左右的因素却不会产生影响吗? - abarnert

0

你可以使用map函数....

map(lambda y: y[0], x)

2
如果你要使用 map,最好使用 itemgetter 而不是 lambda - abarnert

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