2010-07-22 64 views
61

Tôi đang cố gắng lấy các phần tử thứ n từ danh sách các bộ dữ liệu.Làm thế nào để trích xuất các phần tử thứ n từ danh sách các bộ dữ liệu trong python?

Tôi có một cái gì đó như:

elements = [(1,1,1),(2,3,7),(3,5,10)] 

tôi muốn trích xuất chỉ các yếu tố thứ hai của mỗi tuple vào một danh sách:

seconds = [1, 3, 5] 

Tôi biết rằng nó có thể được thực hiện với một vòng lặp for nhưng Tôi muốn biết nếu có một cách khác vì tôi có hàng ngàn bộ dữ liệu.

Trả lời

123
[x[1] for x in elements] 
23

Tôi biết rằng nó có thể được thực hiện với một CHO nhưng tôi muốn biết nếu có một cách khác

Có một cách khác. Bạn cũng có thể làm điều đó với mapitemgetter:

>>> from operator import itemgetter 
>>> map(itemgetter(1), elements) 

này vẫn thực hiện một vòng lặp trong nội bộ và mặc dù nó là hơi chậm hơn so với danh sách hiểu:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter' 
method1 = '[x[1] for x in elements]' 
method2 = 'map(itemgetter(1), elements)' 

import timeit 
t = timeit.Timer(method1, setup) 
print('Method 1: ' + str(t.timeit(100))) 
t = timeit.Timer(method2, setup) 
print('Method 2: ' + str(t.timeit(100))) 

Kết quả:

 
Method 1: 1.25699996948 
Method 2: 1.46600008011 

Nếu bạn cần lặp qua danh sách thì sử dụng for là tốt.

+0

Một bổ sung nhỏ: Trong python-3.x điểm chuẩn sẽ cho thấy rằng bản đồ chỉ mất một phần nhỏ của một phần nghìn giây. Đó là bởi vì nó sẽ trả về một trình lặp. method2 = 'list (map (itemgetter (1), elements))' ám chỉ hành vi cũ. –

+0

Đây phải là câu trả lời được chấp nhận. –

21

này cũng hoạt động:

zip(*elements)[1] 

(tôi chủ yếu là gửi bài này, để chứng minh cho bản thân mình mà tôi đã groked zip ...)

Nhìn thấy nó trong hành động:

>>> help(zip) 

Trợ giúp về chức năng zip tích hợp trong mô-đun builtin:

zip (...)

zip (seq1 [, seq2 [...]]) -> [(seq1 [0], seq2 [0] ...), (...) ]

Trả về danh sách các bộ dữ liệu, trong đó mỗi bộ chứa phần tử thứ i từ mỗi chuỗi đối số. Danh sách được trả lại bị cắt ngắn về độ dài của chuỗi đối số ngắn nhất.

>>> elements = [(1,1,1),(2,3,7),(3,5,10)] 
>>> zip(*elements) 
[(1, 2, 3), (1, 3, 5), (1, 7, 10)] 
>>> zip(*elements)[1] 
(1, 3, 5) 
>>> 

điều Neat Tôi đã học được ngày hôm nay: Sử dụng *list trong lập luận để tạo ra một danh sách tham số cho một hàm ...

+2

và sử dụng '** dict' để tạo đối số từ khóa:' def test (foo = 3, bar = 3): return foo * bar' rồi 'd = {'bar': 9, 'foo' = 12}; kiểm tra in (** d) ' –

+0

@Wayne Werner: Đúng vậy. Công cụ này là tất cả chỉ là kiến ​​thức thụ động (tôi không thường xuyên sử dụng nó) - nhưng nó là tốt để được nhắc nhở bây giờ và sau đó để bạn biết nơi/những gì để tìm kiếm ... –

+0

Câu chuyện có thật - Tôi thấy rằng trong bất cứ điều gì tôi sử dụng thường xuyên đủ (Python, vim), tôi có xu hướng cần nhắc nhở về các tính năng gọn gàng/mát mẻ mà tôi đã quên vì tôi không sử dụng chúng * đó * thường xuyên. –

9

Các mặt hàng này khi tôi đang tìm kiếm đó là cách nhanh nhất để kéo phần tử thứ hai của danh sách 2 tuple.Không phải những gì tôi muốn nhưng chạy cùng một thử nghiệm như hình với một phương pháp thứ 3 cộng với thử nghiệm phương pháp zip

setup = 'elements = [(1,1) for _ in range(100000)];from operator import itemgetter' 
method1 = '[x[1] for x in elements]' 
method2 = 'map(itemgetter(1), elements)' 
method3 = 'dict(elements).values()' 
method4 = 'zip(*elements)[1]' 

import timeit 
t = timeit.Timer(method1, setup) 
print('Method 1: ' + str(t.timeit(100))) 
t = timeit.Timer(method2, setup) 
print('Method 2: ' + str(t.timeit(100))) 
t = timeit.Timer(method3, setup) 
print('Method 3: ' + str(t.timeit(100))) 
t = timeit.Timer(method4, setup) 
print('Method 4: ' + str(t.timeit(100))) 

Method 1: 0.618785858154 
Method 2: 0.711684942245 
Method 3: 0.298138141632 
Method 4: 1.32586884499 

Vì vậy, qua nhanh gấp hai lần nếu bạn có một cặp 2 tuple chỉ chuyển đổi sang một dict và mất các giá trị.

+0

Điều này có lẽ hiển nhiên nhưng tôi sẽ đề cập đến 'dict (elements) .values ​​() 'sẽ dẫn đến một mệnh đề một phần tử trái ngược với danh sách hoặc bản đồ. Đây là chính xác những gì tôi muốn (tôi quan tâm đến các touples độc đáo) (+1 và cảm ơn gửi bài) nhưng những người khác có thể tự hỏi tại sao dict nhanh hơn - nó không cấp phát bộ nhớ nhưng chỉ kiểm tra đối với phần tử hiện có. – Greg0ry

2
map (lambda x:(x[1]),elements) 
+4

Cân nhắc thêm một số giải thích. – fedorqui

0

Thời gian cho Python 3.6 để trích xuất phần tử thứ hai từ một danh sách 2-tuple.

Ngoài ra, thêm numpy phương thức mảng, đơn giản hơn để đọc (nhưng được cho là đơn giản hơn so với danh sách hiểu).

from operator import itemgetter 
elements = [(1,1) for _ in range(100000)] 

%timeit second = [x[1] for x in elements] 
%timeit second = list(map(itemgetter(1), elements)) 
%timeit second = dict(elements).values() 
%timeit second = list(zip(*elements))[1] 
%timeit second = np.array(elements)[:,1] 

và timings:

list comprehension: 4.73 ms ± 206 µs per loop 
list(map):   5.3 ms ± 167 µs per loop 
dict:    2.25 ms ± 103 µs per loop 
list(zip)   5.2 ms ± 252 µs per loop 
numpy array:  28.7 ms ± 1.88 ms per loop 

Lưu ý rằng map()zip() không trả về một danh sách nữa, do đó việc chuyển đổi rõ ràng.

Các vấn đề liên quan