2012-06-20 44 views
5

Tôi đang xây dựng một lớp học với các từ khóa khác với các giá trị danh sách và phím số nguyên. Thêm giá trị cho từ điển này có vẻ là một nút cổ chai thực sự mặc dù và tôi đã tự hỏi liệu có thể có một số cách để tăng tốc độ mã của tôi.Python: cách tối ưu để thêm vào từ điển có giá trị danh sách

class myClass(): 

    def __init__(self): 
    self.d = defaultdict(list) 

    def addValue(self, index, value): 
    self.d[index].append(value) 

Đây có phải là cách tối ưu để thực hiện việc này không? Tôi không thực sự quan tâm đến thứ tự của các giá trị, vì vậy có lẽ có một cấu trúc dữ liệu phù hợp hơn ở đó với một phụ thêm nhanh hơn. Sau đó, một lần nữa, 'phụ thêm' dường như không phải là vấn đề chính, bởi vì nếu tôi chỉ cần nối thêm vào một danh sách trống, mã sẽ nhanh hơn rất nhiều. Tôi đoán đó là tải của danh sách được lưu trữ trước đó mà chiếm hầu hết thời gian?


Tôi phát hiện ra vấn đề không có trong dict, nhưng trong danh sách nối thêm (mặc dù tôi đã tuyên bố khác trong bài đăng gốc của mình, mà tôi xin lỗi). Vấn đề này là do một lỗi trong bộ thu gom rác của Python, được giải thích rõ ràng trên this other question. Vô hiệu hóa gc trước khi thêm tất cả các giá trị và sau đó bật lại nó, tăng tốc quá trình vô cùng!

+2

Thêm các mục vào danh sách và nhận các giá trị từ một đối tượng hoặc một dict không mất thời gian. Để tăng tốc một chương trình bạn tìm thấy nút cổ chai bằng cách lược tả, không phải bằng cách thay đổi các đoạn mã ngẫu nhiên. –

+0

Việc ánh xạ các mục với các khóa hiện có nhanh hơn đáng kể so với việc thêm các giá trị vào các khóa mới? –

+0

Tôi chỉ phát hiện ra rằng vấn đề không phải là trong dict, nhưng trong danh sách phụ thêm (mặc dù tôi tuyên bố khác trong bài gốc của tôi, mà tôi xin lỗi). Sau đó, tôi tìm thấy câu trả lời cho câu hỏi của mình trên http://stackoverflow.com/questions/2473783/is-there-a-way-to-circumvent-python-list-append-becoming-progressively-slower. Vì tôi mới vào trang web này, tôi không biết quy trình chuẩn là gì trong trường hợp này: tôi có nên xóa bài đăng gốc của mình không? Hoặc thêm các chi tiết ở trên và trả lời cho bài đăng? – niefpaarschoenen

Trả lời

0

Như một kết luận, tôi có thể nói rằng mã của tôi trong câu hỏi ban đầu nhanh hơn hoặc nhanh như tất cả các đề xuất khác.

2

Hãy so sánh nó như thế này:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    self.d.setdefault(index, []).append(value) 
+1

Ngoài sự tò mò, tại sao điều này nhanh hơn? Tôi đã nghĩ rằng 'defaultdict' làm một cái gì đó rất giống nhau đằng sau hậu trường. –

+1

Sau một thử nghiệm ngắn, tôi phát hiện ra điều này không nhanh hơn. Tôi chỉ thích nó tốt hơn. – eumiro

+0

Tôi nghĩ rằng nó thực sự làm tương tự đằng sau hậu trường; timings là tương tự trong mọi trường hợp ... Tôi thích defaultdict mặc dù, bởi vì nói chung bạn phải gõ ít hơn. – niefpaarschoenen

1

Họ nói "Tốt hơn để yêu cầu sự tha thứ hơn cho phép.". Bây giờ bạn không yêu cầu sự cho phép cá nhân, nhưng tôi nghĩ có lẽ defaultdict làm, và đó là những gì làm chậm nó xuống.

try này:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    try: 
     self.d[index].append(value) 
    except KeyError: 
     self.d[index] = [value] 

này cố gắng truy cập phím index trong từ điển, nếu nó không tồn tại nó sẽ nâng cao một KeyError, và hành động theo nó.

Có nhanh hơn không?

+0

Tôi đã cố gắng so sánh mã và mã của bạn từ câu hỏi (sử dụng [timeit] (http://docs.python.org/library/timeit.html)). Tôi đã sử dụng thử nghiệm này: 'my = myClass() my.addValue (3," ab ") my.addValue (3," cd ") my.addValue (4," ef ") my.addValue (4, "gh") 'Và mã gốc nhanh hơn! Trên máy của tôi 24,66 usec cho mã của bạn và 18,10 usec cho mã từ câu hỏi. Có vẻ như cách tiếp cận này không phải là câu trả lời .. – stalk

+1

Dường như bạn có giải pháp nhanh nhất sau đó :) – jadkik94

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