2009-12-10 35 views
5

Tôi có một danh sách liệt kê (được tạo ra với một danh sách hiểu đơn giản):Chuyển đổi một danh sách liệt kê một tuple trong Python

>>> base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 
>>> base_lists 

[[1,1],[1,2],[1,3],[1,4],[1,5],[2,1],[2,2],[2,3],[2,4],[2,5]] 

tôi muốn chuyển toàn bộ danh sách này thành một tuple chứa tất cả các giá trị trong danh sách, nghĩa là:

resulting_tuple = (1,1,1,2,1,3,1,4,1,5,2,1,2,2,2,3,2,4,2,5) 

Cách hiệu quả nhất để làm điều này là gì? (Một cách để tạo ra cùng một bộ tuple với list comprehension này cũng sẽ là một câu trả lời có thể chấp nhận được). Tôi đã xem xét các câu trả lời ở đây và trong tài liệu Python, tuy nhiên tôi đã không thể tìm ra một câu phù hợp.

EDIT:

Rất cám ơn đến tất cả những ai đã trả lời!

Trả lời

11
tuple(x for sublist in base_lists for x in sublist) 

Sửa: lưu ý rằng, với base_lists quá ngắn, các genexp (với bộ nhớ không giới hạn có sẵn) là chậm. Hãy xem xét các hồ sơ sau tu.py:

base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 

def genexp(): 
    return tuple(x for sublist in base_lists for x in sublist) 

def listcomp(): 
    return tuple([x for sublist in base_lists for x in sublist]) 

def withsum(): 
    return tuple(sum(base_lists,[])) 

import itertools as it 

def withit(): 
    return tuple(it.chain(*base_lists)) 

Bây giờ là:

$ python -mtimeit -s'import tu' 'tu.genexp()' 
100000 loops, best of 3: 7.86 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withsum()' 
100000 loops, best of 3: 5.79 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withit()' 
100000 loops, best of 3: 5.17 usec per loop 
$ python -mtimeit -s'import tu' 'tu.listcomp()' 
100000 loops, best of 3: 5.33 usec per loop 

Khi danh sách dài hơn (ví dụ, khi hiệu suất thực sự quan trọng) điều này là một chút khác nhau. Ví dụ, đặt một 100 * trên RHS định base_lists:

$ python -mtimeit -s'import tu' 'tu.genexp()' 
1000 loops, best of 3: 408 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withsum()' 
100 loops, best of 3: 5.07 msec per loop 
$ python -mtimeit -s'import tu' 'tu.withit()' 
10000 loops, best of 3: 148 usec per loop 
$ python -mtimeit -s'import tu' 'tu.listcomp()' 
1000 loops, best of 3: 278 usec per loop 

như vậy cho danh sách dài chỉ withsum là một thảm họa thực hiện - những người khác đang ở trong sân chơi bóng chày cùng, mặc dù rõ ràng itertools có rìa, và comprehensions danh sách (khi bộ nhớ phong phú có sẵn, vì nó sẽ luôn luôn trong microbenchmarks ;-) nhanh hơn genexps.

Sử dụng 1000 *, genexp chậm lại khoảng 10 lần (wrt 100 *), withit và listcomp khoảng 12 lần, và withsum khoảng 180 lần (withsum là O(N squared), cộng với nó bắt đầu bị phân mảnh đống nghiêm trọng tại đó kích thước).

+0

Liệu một cách chính xác những gì tôi cần. Cảm ơn Alex! –

3
>>> sum(base_lists,[]) 
[1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5] 
>>> tuple(sum(base_lists,[])) 
(1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5) 
+2

Sử dụng 'sum' cho bất cứ điều gì nhưng con số là một ý tưởng tồi (như tôi thường cố gắng giải thích trong SO - tôi là người khởi tạo của' sum' của Python vì vậy tôi cảm thấy một cảm giác tội lỗi bất cứ khi nào tôi thấy nó bị lạm dụng ;-) . Gợi ý: O (N bình phương). –

+0

Rất tiếc, rất tốt khi biết Alex. Tôi đoán sẽ có một lý do chính đáng tại sao nó không thể là O (N):/ –

2

resulting_tuple = tuple(item for l in base_lists for item in l)

5
from itertools import chain 
base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 

print tuple(chain(*base_lists)) 
+0

Đã bỏ phiếu cho việc sử dụng itertools, đây là một mô-đun đánh giá thấp –

0
>>> arr=[] 
>>> base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 
>>> [ arr.extend(i) for i in base_lists ] 
[None, None, None, None, None, None, None, None, None, None] 
>>> arr 
[1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5] 
>>> tuple(arr) 
(1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5) 
Các vấn đề liên quan