Zip với đầu ra danh sách thay vì tuple


94

Cách nhanh nhất và thanh lịch nhất của danh sách từ hai danh sách là gì?

Tôi có

In [1]: a=[1,2,3,4,5,6]

In [2]: b=[7,8,9,10,11,12]

In [3]: zip(a,b)
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)]

Và tôi muốn có

In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]

Tôi đã nghĩ đến việc sử dụng bản đồ thay vì zip, nhưng tôi không biết liệu có phương pháp thư viện tiêu chuẩn nào đó để đặt làm đối số đầu tiên hay không.

Tôi có thể xác định chức năng của riêng mình cho việc này và sử dụng bản đồ, câu hỏi của tôi là liệu đã có cái gì đó được triển khai chưa. Không cũng là một câu trả lời.


1
Chà, bạn có thực sự cần danh sách không? Bạn sẽ làm gì với kết quả?
Karl Knechtel

14
Một ví dụ sẽ là sklearn, trong đó nhiều lần dữ liệu phải được tổ chức theo kiểu này.
tumultous_rooster

Câu trả lời:


101

Nếu bạn đang nén nhiều hơn 2 danh sách (hoặc thậm chí chỉ 2, cho vấn đề đó), một cách có thể đọc được sẽ là:

[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]

Điều này sử dụng khả năng hiểu danh sách và chuyển đổi từng phần tử trong danh sách (bộ giá trị) thành danh sách.


54

Bạn gần như đã có câu trả lời cho chính mình. Không sử dụng mapthay vì zip. Sử dụng map AND zip .

Bạn có thể sử dụng bản đồ cùng với mã zip để có cách tiếp cận tiện dụng, thanh lịch:

list(map(list, zip(a, b)))

ziptrả về một danh sách các bộ giá trị. map(list, [...])cuộc gọi listtrên từng bộ trong danh sách. list(map([...])biến đối tượng bản đồ thành một danh sách có thể đọc được.


quyết định không may khi thực hiện các hoạt động thu thập python 3 trả về một generatoráp đặt chi phí gấp đôi listở đây.
StephenBoesch

15

Tôi thích sự sang trọng của hàm zip, nhưng sử dụng hàm itemgetter () trong mô-đun toán tử dường như nhanh hơn nhiều. Tôi đã viết một tập lệnh đơn giản để kiểm tra điều này:

import time
from operator import itemgetter

list1 = list()
list2 = list()
origlist = list()
for i in range (1,5000000):
        t = (i, 2*i)
        origlist.append(t)

print "Using zip"
starttime = time.time()
list1, list2 = map(list, zip(*origlist))
elapsed = time.time()-starttime
print elapsed

print "Using itemgetter"
starttime = time.time()
list1 = map(itemgetter(0),origlist)
list2 = map(itemgetter(1),origlist)
elapsed = time.time()-starttime
print elapsed

Tôi mong đợi zip sẽ nhanh hơn, nhưng phương pháp itemgetter sẽ thắng bằng một cú đánh dài:

Using zip
6.1550450325
Using itemgetter
0.768098831177

2
Đây là sự hoán đổi những gì OP đang cố gắng thực hiện. Bạn có thể cập nhật bài đăng của mình để phản ánh điều đó không? Tức là OP đang chuyển đổi hai danh sách thành danh sách hoặc số lượng cặp tùy ý. Bạn đang chuyển đổi một số cặp tùy ý thành một cặp danh sách.
Mad Physicist,

Phiên bản này được đo bằng python nào?
Moberg

Tôi không nhớ, đã hơn hai năm trước, nhưng rất có thể là 2,6 hoặc 2,7. Tôi tưởng tượng bạn có thể sao chép mã và thử nó trên phiên bản / nền tảng của riêng bạn.
kslnet

2
python 2 ziptạo một danh sách thực. Điều đó làm chậm mọi thứ. Hãy thử thay thế zipbằng itertools.izipthen.
Jean-François Fabre

Trong Python 3.5, zip mất 3,5 giây và itemgetter mất 0,10 giây. Đối với những người thích hiểu danh sách, list1 = [x[0] for x in origlist]hoạt động tốt list1 = map(itemgetter(0), origlist).
Elias Strehle

3

Tôi thường không thích sử dụng lambda, nhưng ...

>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = lambda a, b: [list(c) for c in zip(a, b)]
>>> c(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

Nếu bạn cần thêm tốc độ, bản đồ sẽ nhanh hơn một chút:

>>> d = lambda a, b: map(list, zip(a, b))
>>> d(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

Tuy nhiên, bản đồ được coi là không phức tạp và chỉ nên được sử dụng để điều chỉnh hiệu suất.


4
Thêm gì lambdaở đây? Người ta chỉ có thể viết biểu thức thay vì gọi một hàm (nó thực sự không phức tạp) và ngay cả khi người ta muốn một hàm cho nó, nó có thể được định nghĩa dễ dàng trong hai dòng (một dòng nếu khóa trả về của bạn bị hỏng hoặc bạn mất trí) . mapmặt khác là hoàn toàn ổn nếu đối số đầu tiên là một hàm thuần túy (trái ngược với a lambda).

1
Vâng, anh ấy đã yêu cầu một chức năng. Nhưng tôi đồng ý - có lẽ tốt hơn chỉ nên trả thêm tiền. Đối với bản đồ, tôi tin rằng khả năng hiểu danh sách hầu như luôn rõ ràng hơn.
Ceasar Bautista

1
Tôi muốn giới thiệu maphơn lambda. vậy map(list, zip(a,b)). Khả năng hiểu danh sách có thể rõ ràng hơn một chút, nhưng bản đồ sẽ nhanh hơn (chưa được kiểm tra)
thanh

Ý tôi là, một lần nữa, nếu OP cần tốc độ, bản đồ là cách để đi. Nhưng nói chung, và đặc biệt là trong Python, hãy nhấn mạnh khả năng đọc qua tốc độ (nếu không thì bạn nhúng tay vào việc tối ưu hóa sớm).
Ceasar Bautista

3

Còn cái này thì sao?

>>> def list_(*args): return list(args)

>>> map(list_, range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Hoặc thậm chí tốt hơn:

>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Đối với tôi, đó dường như là một câu trả lời tốt hơn phần còn lại vì ở đây chúng tôi đang giảm một bước bằng cách không thực hiện zip và trực tiếp tạo danh sách. Tuyệt vời
Akshay Hazari

2

Sử dụng numpy

Định nghĩa về sự thanh lịch có thể khá đáng nghi ngờ nhưng nếu bạn đang làm việc với numpyviệc tạo một mảng và việc chuyển đổi nó thành danh sách (nếu cần ...) có thể rất thực tế mặc dù không hiệu quả lắm so với việc sử dụng maphàm hoặc toàn bộ danh sách.

import numpy as np 
a = b = range(10)
zipped = zip(a,b)
result = np.array(zipped).tolist()
Out: [[0, 0],
 [1, 1],
 [2, 2],
 [3, 3],
 [4, 4],
 [5, 5],
 [6, 6],
 [7, 7],
 [8, 8],
 [9, 9]]

Nếu không, bỏ qua zipchức năng bạn có thể sử dụng trực tiếp np.dstack:

np.dstack((a,b))[0].tolist()

1

Tôi đoán là hiểu danh sách sẽ là giải pháp rất đơn giản.

a=[1,2,3,4,5,6]

b=[7,8,9,10,11,12]

x = [[i, j] for i, j in zip(a,b)]

print(x)

output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
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.