Làm thế nào để hợp nhất danh sách vào một danh sách các bộ dữ liệu?


298

Cách tiếp cận Pythonic để đạt được những điều sau đây là gì?

# 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)]

Mỗi thành viên của list_cmột tuple, có thành viên đầu tiên đến từ list_avà thành viên thứ hai đến từ list_b.

Câu trả lời:


443

Trong 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)]

Trong 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
bạn phải biết rằng chức năng zip dừng ở cuối danh sách ngắn nhất, có thể không phải luôn luôn là những gì bạn muốn. các itertoolsmô-đun định nghĩa một zip_longest()phương pháp mà dừng lại ở phần cuối của danh sách dài nhất, điền giá trị thiếu với một cái gì đó mà bạn cung cấp như một tham số.
Adrien Plisson

5
@Adrien: chúc mừng cho nhận xét áp dụng của bạn. Đối với Python 2.x , s/zip_longest()/izip_longest(). Đổi tên trong Python 3.x thành zip_longest().
Mechanical_meat

Tôi có thể tạo [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6), v.v. bằng cách sử dụng lệnh zip không?
Mona Jalal

3
@MonaJalal: không, điều đó không được ghép nối, đó là tạo ra sản phẩm của danh sách. itertools.product()làm điều đó
Martijn Pieters

2
lưu ý, ít nhất trong python3.6 zip không trả về danh sách. Vì vậy, bạn cần có danh sách (zip (list_a, list_b))
Supamee

141

Trong python 3.0 zip trả về một đối tượng zip. Bạn có thể lấy một danh sách ra khỏi nó bằng cách gọi list(zip(a, b)).


3
Điều này có thể là tầm thường, nhưng được cảnh báo rằng việc sử dụng trực tiếp trong vòng lặp for cung cấp cho bạn một trình tạo sẽ cạn kiệt sau khi sử dụng một lần. Lưu vào một biến nếu bạn muốn sử dụng nó thường xuyên hơn
Hakaishin

13

Bạn có thể sử dụng bản đồ lambda

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

Điều này cũng sẽ hoạt động nếu có độ dài của danh sách gốc không khớp


1
Tại sao nên sử dụng lambda? map(None, a,b)
Padraic Cickyham

Tôi chỉ có quyền truy cập vào python 3.5.
Hiệp sĩ bóng đêm

3
Nếu bạn đang sử dụng python3 thì c sẽ không phải là một danh sách, nó sẽ là một đối tượng bản đồ, sử dụng lambda sẽ kém hiệu quả hơn nhiều so với việc nén, nếu bạn có danh sách độ dài khác nhau và muốn xử lý thì bạn sẽ sử dụng izip_longest / zip_longest
Padraic


6

Tôi không chắc đây có phải là cách pythonic hay không nhưng điều này có vẻ đơn giản nếu cả hai danh sách có cùng số lượng phần tử:

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

Tôi biết đây là một câu hỏi cũ và đã được trả lời, nhưng vì một số lý do, tôi vẫn muốn đăng giải pháp thay thế này. Tôi biết thật dễ dàng để tìm ra chức năng tích hợp nào thực hiện "phép thuật" mà bạn cần, nhưng sẽ không đau khi biết bạn có thể tự làm điều đó.

>>> 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
Thay đổi một trong các danh sách đầu vào (nếu chúng khác nhau về độ dài) không phải là một hiệu ứng phụ đẹp. Ngoài ra, hai bài tập cardtrong if-elifkhông cần thiết, đó là lý do tại sao bạn có continue. (Trên thực tế, không có continuebạn sẽ không phải thay đổi danh sách: cả hai bài tập được đề cập trước đó nên được giữ và trở thành card = (list_1[i], '')card = ('', list_2[1])tương ứng.)
ᴠɪɴᴄᴇɴᴛ

5

Đầu ra mà bạn đã hiển thị trong báo cáo vấn đề không phải là tuple mà là danh sách

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

kiểm tra

type(list_c)

xem xét bạn muốn kết quả là tuple ra khỏi list_a và list_b, hãy làm

tuple(zip(list_a,list_b)) 

Theo quan điểm của tôi, có vẻ như đó là những gì tôi đang tìm kiếm và hoạt động tốt cho cả hai (danh sách và bộ dữ liệu). Bởi vì khi bạn sử dụng in , bạn sẽ thấy giá trị phù hợp (như được mong đợi và được đề cập bởi @cyborg và @Lodewijk) và không có gì liên quan đến đối tượng như: <map object at 0x000001F266DCE5C0>hoặc <zip object at 0x000002629D204C88>. Ít nhất, giải pháp về bản đồzip (một mình) dường như chưa hoàn chỉnh (hoặc quá phức tạp) đối với tôi.
Wagner_SOFC

1
Câu hỏi cho biết họ muốn một danh sách các bộ dữ liệu không phải là một bộ dữ liệu.
goryh

1

Một thay thế mà không sử dụng zip:

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

Trong trường hợp người ta muốn không chỉ nhận được 1 với 1, 2 với 2 ... mà tất cả các kết hợp có thể có của 2 danh sách, điều đó sẽ được thực hiện với

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.