Giữ bản đồ các thành phần đã xem với id được liên kết.
from itertools import count
from collections import defaultdict
mapping = defaultdict(count().__next__)
result = []
for element in my_list:
result.append(mapping[tuple(element)])
bạn cũng có thể sử dụng danh sách-hiểu:
result = [mapping[tuple(element)] for element in my_list]
Thật không may list
s không hashable vì vậy bạn phải chuyển đổi chúng sang một tuple
khi lưu trữ chúng như là chìa khóa của việc lập bản đồ.
Lưu ý lừa của việc sử dụng defaultdict
, và count().__next__
để cung cấp id tăng độc đáo. Trên python2, bạn phải thay thế .__next__
bằng .next
.
defaultdict
sẽ chỉ định giá trị mặc định khi không tìm thấy khóa. Giá trị mặc định thu được bằng cách gọi hàm được cung cấp trong hàm tạo. Trong trường hợp này, phương pháp __next__
của máy phát điện count()
mang lại số lượng ngày càng tăng.
Là một thay thế khả năng di chuyển bạn có thể làm:
from functools import partial
mapping = defaultdict(partial(next, count()))
Một giải pháp thay thế, như đề xuất trong các ý kiến, là chỉ cần sử dụng các chỉ số như id duy nhất:
result = [my_list.index(el) for el in my_list]
Tuy nhiên, đây là một ví dụ:
- Nó tak es O (N^2) thời gian thay vì O (N)
- Các id là duy nhất, tăng nhưng không liên tục (có thể hoặc không thể là một vấn đề)
Để so sánh hai giải pháp xem:
In [1]: from itertools import count
...: from collections import defaultdict
In [2]: def hashing(seq):
...: mapping = defaultdict(count().__next__)
...: return [mapping[tuple(el)] for el in seq]
...:
In [3]: def indexing(seq):
...: return [seq.index(i) for i in seq]
...:
In [4]: from random import randint
In [5]: seq = [[randint(1, 20), randint(1, 20), randint(1, 20)] for _ in range(90000)]
In [6]: %timeit hashing(seq)
10 loops, best of 3: 37.7 ms per loop
In [7]: %timeit indexing(seq)
1 loop, best of 3: 26 s per loop
Note thế nào để có danh sách các yếu tố 90k giải pháp lập bản đồ mất ít 40 mili giây trong khi các giải pháp lập chỉ mục mất 26 giây .
Làm id phải được tuần tự? bạn có thể dễ dàng lạm dụng phương thức 'index' của danh sách nếu không:' def get_ids (li): trả về [li.index (i) cho i in li]; 'trả về' [0, 1, 0, 1, 4] 'cho' [[1,2,3], [1,2,4], [1,2,3], [1,2,4], [1,2,5]] ' – DeepSpace
@DeepSpace O (N^2) thời gian. Nó có thể được cải thiện bằng cách tính toán một bản sao được sắp xếp của danh sách và sử dụng 'bisect' để kết hợp một chỉ mục một cách hiệu quả với nó, làm cho thời gian O (N log N) là hướng xuống để giải quyết vấn đề này bằng cách so sánh. – Bakuriu