2010-09-09 50 views
14

câu hỏi của tôi là, là tôi có một danh sách như sau:python đa chiều danh sách .. làm thế nào để lấy một kích thước?

someList = [[0,1,2],[3,4,5],[6,7,8]] 

làm thế nào tôi sẽ nhận được sự xâm nhập đầu tiên của mỗi sublist?

Tôi biết tôi có thể làm điều này:

newList = [] 
for entry in someList: 
    newList.append(entry[0]) 

nơi newList sẽ là:

[0, 3, 6] 

Nhưng có một cách để làm điều gì đó như:

newList = someList[:][0] 

?

EDIT:

Hiệu quả là mối quan tâm lớn. Tôi đang thực sự trải qua một danh sách đó có hơn 300000 mục

Trả lời

17

EDIT: Dưới đây là một số con số thực tế! Các izip, danh sách hiểu, và numpy cách làm điều này là tất cả về cùng một tốc độ.

# zip 
>>> timeit.timeit("newlist = zip(*someList)[0]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10) 
1.4984046398561759 

# izip 
>>> timeit.timeit("newlist = izip(*someList).next()", setup = "someList = range(1000000), range(1000000), range(1000000)]; from itertools import izip", number = 10) 
2.2186223645803693e-05 

# list comprehension 
>>> timeit.timeit("newlist = [li[0] for li in someList]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10) 
1.4677040212518477e-05 

# numpy 
>>> timeit.timeit("newlist = someList[0,:]", setup = "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)])", number = 10) 
6.6217344397045963e-05 
>>> 

Đối với các cấu trúc dữ liệu lớn như thế này bạn nên sử dụng numpy, mà implementes một kiểu mảng trong C và do đó hiệu quả hơn đáng kể. Nó cũng cung cấp tất cả các thao tác ma trận mà bạn mong muốn.

>>> import numpy as np 
>>> foo = np.array([[0,1,2],[3,4,5],[6,7,8]]) 
>>> foo[:,0] 
array([0, 3, 6]) 

Bạn cũng có thể transpose ...

>>> foo.transpose() 
array([[0, 3, 6], 
     [1, 4, 7], 
     [2, 5, 8]]) 

... làm việc với mảng n chiều ...

>>> foo = np.zeros((3,3,3)) 
>>> foo 
array([[[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]], 

     [[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]], 

     [[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]]) 
>>> foo[0,...] 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 

..do hiệu quả đại số tuyến tính ...

>>> foo = no.ones((3,3)) 
>>> np.linalg.qr(foo) 
(array([[-0.57735027, 0.81649658, 0.  ], 
     [-0.57735027, -0.40824829, -0.70710678], 
     [-0.57735027, -0.40824829, 0.70710678]]), array([[ -1.73205081e+00, -1. 
73205081e+00, -1.73205081e+00], 
     [ 0.00000000e+00, -1.57009246e-16, -1.57009246e-16], 
     [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]])) 

... và về cơ bản là anything that Matlab can.

+0

WOW, cảm ơn rất nhiều. Đây là SUPER FAST so với các giải pháp khác. Nếu tôi có thể +100000, tôi sẽ – Richard

+1

@Richard: Điều đó phụ thuộc ... danh sách càng lớn thì giải pháp hiểu và giải nén tốt hơn sẽ hoạt động tốt hơn, bởi vì họ không xem xét phần lớn các mục nhập ma trận. –

+2

@jellybean: Tôi nghi ngờ rằng ... numpy thực sự được tối ưu hóa khá tốt. Tôi nghĩ rằng nó an toàn để nói rằng một slice đơn giản khôn ngoan sẽ không đọc toàn bộ ma trận. (Mặc dù tôi có thể sai, nhưng tôi không biết chi tiết thực hiện của C). Thực tế, tôi nghĩ rằng 'numpy' sẽ thực hiện * tốt hơn * với một danh sách lớn hơn, vì chi phí của kiểu' list' gốc của Python bắt đầu để thêm lên. Nhưng tất nhiên, chỉ có một cách để tìm ra! – katrielalex

8
zip(*someList)[0] 

EDIT:

Đáp lại bình luận đệ quy của: Người ta cũng có thể sử dụng

from itertools import izip 
izip(*someList).next() 

cho hiệu suất tốt hơn.

Một số thời gian phân tích:

python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = zip(*someList)[0]" 
10 loops, best of 3: 498 msec per loop 
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; from itertools import izip; newlist = izip(*someList).next()" 
10 loops, best of 3: 111 msec per loop 
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = [li[0] for li in someList]" 
10 loops, best of 3: 110 msec per loop 

Vì vậy izip và danh sách hiểu chơi trong cùng một giải đấu.

Tất nhiên, việc hiểu danh sách linh hoạt hơn khi bạn cần chỉ mục khác 0 và rõ ràng hơn.

EDIT2:

Ngay cả những giải pháp NumPy là không nhanh (nhưng tôi có thể lựa chọn một ví dụ không đại diện):

python -m timeit "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)]); newList = someList[:,0]" 
10 loops, best of 3: 551 msec per loop 
+0

Nếu someList là lớn, điều này sẽ làm rất nhiều công việc không cần thiết, bằng cách kết hợp tất cả các cột khác quá. – recursive

10

Perfect trường hợp cho một list comprehension:

[sublist[0] for sublist in someList] 

Vì hiệu quả là mối quan tâm chính, điều này sẽ nhanh hơn nhiều so với phương pháp zip. Tùy theo những gì bạn đang làm với kết quả, bạn có thể để có được hiệu quả nhiều hơn bằng cách sử dụng phương pháp biểu hiện máy phát điện:

(sublist[0] for sublist in someList) 

Lưu ý rằng điều này trả về một máy phát điện thay vì một danh sách mặc dù, vì vậy không thể được được lập chỉ mục vào.

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