如何将列表合并为元组列表?


297

实现以下目标的Python方法是什么?

# Original lists:

list_a = [1, 2, 3, 4]
list_b = [5, 6, 7, 8]

# List of tuples from 'list_a' and 'list_b':

list_c = [(1,5), (2,6), (3,7), (4,8)]

的每个成员list_c都是一个元组,其第一个成员是from list_a,第二个成员是from list_b

Answers:


442

在Python 2中:

>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> zip(list_a, list_b)
[(1, 5), (2, 6), (3, 7), (4, 8)]

在Python 3中:

>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> list(zip(list_a, list_b))
[(1, 5), (2, 6), (3, 7), (4, 8)]

77
您必须知道zip功能在最短列表的末尾停止,而列表可能并不总是您想要的。该itertools模块定义了一个zip_longest()方法,该方法在最长列表的末尾停止,用您提供的参数填充缺失值。
Adrien Plisson 2010年

5
@Adrien:为您的适用评论打气。对于Python 2.x ,s/zip_longest()/izip_longest()。在Python 3.x中重命名为zip_longest()
mechanical_meat

我可以使用zip命令创建[(1,5),(1,6),(1,7),(1,8),(2,5),(2,6)等吗?
蒙娜·贾拉

3
@MonaJalal:不,这不是配对,而是创建列表的产品itertools.product()做到这一点。
马丁·彼得斯

2
注意,至少在python3.6中zip不返回列表。因此,您需要使用list(zip(list_a,list_b))代替
Supamee

141

在python 3.0中,zip返回一个zip对象。您可以致电以获得清单list(zip(a, b))


3
这可能是微不足道的,但请注意,直接在for循环中使用它会为您提供一个生成器,该生成器在使用一次后将被耗尽。保存到变量中(如果您想更频繁地使用它)
Hakaishin

13

您可以使用地图lambda

a = [2,3,4]
b = [5,6,7]
c = map(lambda x,y:(x,y),a,b)

如果原始列表的长度不匹配,这也将起作用


1
为什么要使用lambda?map(None, a,b)
Padraic Cunningham

我只能访问python 3.5。
黑暗骑士

3
如果您使用的是python3,则c不会是列表,而将是一个地图对象,而且如果您使用不同的长度列表并要处理该列表,那么使用lambda的效率将比仅使用zip的效率低很多。 izip_longest / zip_longest
Padraic Cunningham


6

我不确定这是否是pythonic方式,但是如果两个列表具有相同数量的元素,这似乎很简单:

list_a = [1, 2, 3, 4]

list_b = [5, 6, 7, 8]

list_c=[(list_a[i],list_b[i]) for i in range(0,len(list_a))]

5

我知道这是一个古老的问题,已经得到回答,但是由于某些原因,我仍然想发布此替代解决方案。我知道很容易找出哪个内置函数可以完成您所需的“魔术”,但是知道您可以自己完成该操作也不会有什么害处。

>>> list_1 = ['Ace', 'King']
>>> list_2 = ['Spades', 'Clubs', 'Diamonds']
>>> deck = []
>>> for i in range(max((len(list_1),len(list_2)))):
        while True:
            try:
                card = (list_1[i],list_2[i])
            except IndexError:
                if len(list_1)>len(list_2):
                    list_2.append('')
                    card = (list_1[i],list_2[i])
                elif len(list_1)<len(list_2):
                    list_1.append('')
                    card = (list_1[i], list_2[i])
                continue
            deck.append(card)
            break
>>>
>>> #and the result should be:
>>> print deck
>>> [('Ace', 'Spades'), ('King', 'Clubs'), ('', 'Diamonds')]

2
更改输入列表之一(如果它们的长度不同)不是一个很好的副作用。另外,不需要对card中的两个分配if-elif,这就是为什么要使用的原因continue。(实际上,没有,continue您不必更改列表:前面提到的两个任务都应保留card = (list_1[i], '')card = ('', list_2[1])分别成为和。)
ᴠɪɴᴄᴇɴᴛ

5

您在问题陈述中显示的输出不是元组而是列表

list_c = [(1,5), (2,6), (3,7), (4,8)]

检查

type(list_c)

考虑到您想要结果作为list_a和list_b中的元组,请执行

tuple(zip(list_a,list_b)) 

从我的角度来看,这似乎是我正在寻找的东西,并且两者(列表和元组)都可以正常工作。因为当您使用print时,您将看到正确的值(如预期并由@cyborg和@Lodewijk提及),并且与对象无关的内容如:<map object at 0x000001F266DCE5C0><zip object at 0x000002629D204C88>。至少,对我而言,关于mapzip(单独)的解决方案似乎不完整(或过于复杂)。
Wagner_SOFC'5

1
问题表明,他们想要一个元组列表,而不是一个元组列表。
goryh

1

一种不使用的替代方法zip

list_c = [(p1, p2) for idx1, p1 in enumerate(list_a) for idx2, p2 in enumerate(list_b) if idx1==idx2]

万一不仅要获取元组1st与1st,2nd与2nd ...而且要获取2个列表的所有可能组合,可以使用

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
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.