2011-07-01 34 views
10

Có cách nào đơn giản để lấy chỉ mục của một mục mà tôi vừa thêm vào danh sách không? Tôi cần theo dõi mục được thêm gần đây nhất.Nhận chỉ mục của mục được thêm gần đây

tôi đã đưa ra hai giải pháp khả thi:

# Workaround 1 
# The last added is the one at index len(li) - 1 
>> li = ['a', 'b', 'c',] 
>> li.append('d') 
>> last_index = len(li) - 1 
>> last_item = li[len(li) - 1] 

# Workaround 2 
# Use of insert at index 0 so I know index of last added 
>> li = ['a', 'b', 'c',] 
>> li.insert(0, 'd') 
>> last_item = li[0] 

Có một thủ thuật để có được những chỉ số của một mục nối?

Nếu không, bạn sẽ sử dụng điều gì ở trên và tại sao? Bất kỳ cách giải quyết khác nào bạn đề xuất?

Trả lời

16

li[-1] là mục cuối cùng trong danh sách, và do đó một trong đó gần đây nhất đã được nối vào cuối của nó:

>>> li = [1, 2, 3] 
>>> li.append(4) 
>>> li[-1] 
4 

Nếu bạn cần chỉ mục, không mục, sau đó len(li) - 1 chỉ là tốt, và rất hiệu quả (vì len(li) được tính trong thời gian liên tục - xem dưới đây)


trong nguồn CPython, len cho các danh sách được ánh xạ tới hoạt list_length trong.210:

static Py_ssize_t 
list_length(PyListObject *a) 
{ 
    return Py_SIZE(a); 
} 

Py_SIZE chỉ là một macro để truy cập vào các thuộc tính kích thước của tất cả các đối tượng Python, quy định tại Include/object.h:

#define Py_SIZE(ob)  (((PyVarObject*)(ob))->ob_size) 

Do đó, len(lst) về bản chất là một con trỏ dereference duy nhất.

+0

Một chút về hiệu quả của len (li). – romeroqj

+0

@horhay: vì bạn thích nó, tôi đã thêm một số chi tiết khác được lấy trực tiếp * từ nguồn * –

+0

cảm ơn bạn đã đi sâu hơn! :) – romeroqj

3

Bạn có thể lập chỉ mục danh sách từ hai bên. Chỉ mục của phần tử cuối cùng luôn là -1, bạn không cần phải gọi len. Lặp đi lặp lại chèn lúc đầu là rất không hiệu quả (yêu cầu tất cả các yếu tố trong danh sách được di chuyển một nơi xuống).

+2

Sự hiểu biết của tôi là OP muốn có chỉ mục "có thể tái sử dụng/tuyệt đối". Nói cách khác, chỉ mục có thể được sử dụng để theo dõi giá trị ngay cả khi các yếu tố khác sẽ được nối vào danh sách (-1 là "không thể tái sử dụng/tương đối" ... nhưng có lẽ tôi đang nghĩ đến xa? – mac

+0

@mac you sẽ không đi xa, thực sự tôi nghĩ đề xuất của bạn là tuyệt vời nhưng về lâu dài, tôi có khả năng sẽ phải đối phó với những giới hạn mà bạn đã đề cập về các không gian tên và việc duy trì chỉ mục đó thông qua các lợi nhuận. về hiệu quả của len (li) là OK Đánh giá cao sự giúp đỡ của bạn! – romeroqj

3

Giải pháp thứ ba có thể là phân lớp list và ghi đè phương pháp append, để nó tự động lưu trữ trong thuộc tính như mylist.last_added bất cứ khi nào bạn gọi.

Cách tiếp cận này - nếu mở rộng đến các phương pháp danh sách khác - cung cấp các lợi thế mà bạn có khả năng có thể tạo ra một lớp nơi mà nó sẽ theo dõi các chỉ số của các bổ sung yếu tố cuối cùng bất của phương pháp được sử dụng (insert, append, hoặc phân công đơn giản mylist[some_index] = some_value).

Một ưu điểm khác của việc nhúng thông tin này vào đối tượng danh sách là bạn sẽ vượt qua nó mà không phải lo lắng về không gian tên (vì vậy, bạn sẽ có thể lấy nó ngay cả khi danh sách của bạn được chuyển qua return hoặc yield.).

+0

Tôi đề nghị phân lớp [collections.MutableSequence] (http://docs.python.org/library/collections.html#abcs-abstract-base-classes) [ABC] (http://en.wikipedia.org/wiki/Abstract_base_class) thay vì danh sách. Điều này giúp dễ dàng "nắm bắt" mọi cách mà danh sách mở rộng của bạn có thể được sử dụng và bạn chỉ cần triển khai 5 phương pháp. Xem [this] (http://stackoverflow.com/questions/241141/python-lazy-list/5104787#5104787) câu trả lời (plug shameless). –

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