将列表/元组中的一对对值拆分为两个列表/元组

272
我有一个长这样的列表:
my_list = [('1','a'),('2','b'),('3','c'),('4','d')]

我想把这个列表分成两个列表。

list1 = ['1','2','3','4']
list2 = ['a','b','c','d']

我可以用以下方式完成:

list1 = []
list2 = []
for i in list:
   list1.append(i[0])
   list2.append(i[1])

但我想知道是否有更加优雅的解决方案。


23
请勿使用内置类型名称作为变量名。不要称其为“list”。一旦您创建了一个名为“list”的变量,由于内置函数“list()”被隐藏,您开始遇到奇怪的问题。 - S.Lott
9
那是一个元组,不是列表。在Python中区分它们很重要,尽管它们可以类似地使用。 - Russell Borogove
2个回答

526
>>> source_list = [('1','a'),('2','b'),('3','c'),('4','d')]
>>> list1, list2 = zip(*source_list)
>>> list1
('1', '2', '3', '4')
>>> list2
('a', 'b', 'c', 'd')

编辑:请注意,zip(*可迭代对象)是其自身的逆操作:

>>> list(source_list) == zip(*zip(*source_list))
True
当解包成两个列表时,它变成了:
>>> list1, list2 = zip(*source_list)
>>> list(source_list) == zip(list1, list2)
True

rocksportrocker建议的加法。


7
如果你不熟悉“splat”(星号)运算符,可以参考https://dev59.com/wG435IYBdhLWcg3wvyw5中的解答。 - dicato
37
我想指出zip(*list_of_pairs)的结果不是一对列表,而是元组。在某些情况下(例如附加到它),这种差异可能很重要。因此,在示例中,list1list2应该是tuple1tuple2 - Causality
@Causality 绝对正确。我使用了问题中使用的相同名称,它们也是 tuple。当最初发布此问题时,在问题的评论中指出了错误:https://dev59.com/hmsz5IYBdhLWcg3w8Mir#7558990?noredirect=1#comment9163175_7558908 - agf
3
这一切都很好,直到你得到一个长度为零的 source_list。然后你会得到一个错误,而不是像你期望的那样得到两个空列表。 - robot_rover

40
list1 = (x[0] for x in source_list)
list2 = (x[1] for x in source_list)

4
如果你需要实际的 list 并可以进行索引,那么应该使用方括号 [] 而不是圆括号来创建列表推导式,这样就可以生成 list 而非生成器表达式。 - agf
7
使用zip()函数的解决方案更符合Pythonic风格,而且不需要两个for循环。 - naeg
22
@naeg,这是一种完全正确的Python表达式,并符合Pythonic的风格。你甚至可以争论对于那些不太熟练的程序员来说,这比使用相当模糊的zip(*...)语法更好。 - KillianDS
2
@KillianDS:嗯,我不认为zip()函数或参数解包是复杂或模糊的?由于zip答案获得了更多的赞同,我想其他人也持有相同的看法。 - naeg
4
这取决于原始列表中元组的长度。 如果长度未知或超过2,则使用 zip(*) 更好,否则,这里提供的解决方案也不错。 - Causality
显示剩余2条评论

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