2017-09-22 19 views
9

Tôi có một danh sách, nói A = [[3,5],[1,3],[6,1]].Python Sắp xếp danh sách dựa trên một đơn đặt hàng nhất định

Và tôi có một danh sách khác, nói B = [6,1,3]

Tôi muốn sắp xếp danh mục A để A trở nên [[6,1],[1,3],[3,5]], mà phù hợp với B. trao Tức là các thành viên đầu tiên của mỗi Một sublist nên được sắp xếp theo B.

+0

mã ban đầu của bạn với hành động sắp xếp? – RomanPerekhrest

+2

nếu mục B không tồn tại trong A thì sao? Tôi cũng giả sử A, B có cùng chiều dài. – coder

+0

@coder Tôi không nghĩ có bất kỳ vấn đề nào nếu 'B' không tồn tại trong' A'. Đó là khi số từ 'A' không tồn tại trong' B'. Nó loại ám chỉ sự sắp xếp của bạn vô nghĩa khi thứ tự được định nghĩa trong 'B'. –

Trả lời

8

Bạn có thể tra cứu trong đó mỗi yếu tố [0] của A nằm sử dụng .index trong B

>>> sorted(A, key = lambda i: B.index(i[0])) 
[[6, 1], [1, 3], [3, 5]] 

hoặc tại chỗ loại

>>> A.sort(key = lambda i: B.index(i[0])) 
>>> A 
[[6, 1], [1, 3], [3, 5]] 
+7

'list.index' thực sự không phải là rất hiệu quả ở đây ... –

+6

Đây là câu trả lời hay nếu bạn thích mã chậm và không hiệu quả. –

+5

@ cᴏʟᴅsᴘᴇᴇᴅ Bạn được tự do đề xuất một giải pháp thay thế :) Đây là những gì tôi nghĩ đến trong 6 phút giữa việc đọc câu hỏi và khi tôi viết câu trả lời của mình. Nếu tốc độ là lớn của một thỏa thuận có tối ưu hóa được thực hiện – CoryKramer

2

Điều này rất giống với câu trả lời của CoryKramer nhưng nó nhanh hơn một chút. Thay vì sử dụng chức năng sắp xếp, hãy chèn các mục vào danh sách khác theo cách thủ công. Bằng cách này, phương thức index được gọi ít thường xuyên hơn. (Mã này giả định các phần tử trong b là khác nhau).

a= [[3,5],[1,3],[6,1]] 
b=[6,1,3] 

c= [-1]*len(b) # dummy data 

for x in a: 
    c[b.index(x[0])]= x 

print(c) 
+1

Điều này sẽ không hoạt động nếu 'a = [[3,5], [1,3], [6,1], [1,7]]' và 'b = [6,1,3,1]' – coder

+1

@coder OP không chỉ định bất kỳ thứ gì như thế nên tôi giả định các phần tử trong danh sách b sẽ khác biệt. – Anonta

+1

bạn tốt hơn đề cập đến giả định đó cho câu trả lời của bạn sau đó. – coder

13

dẫn xuất dict ánh xạ các số trong B đến chỉ mục của chúng và sử dụng trong các chức năng khóa sắp xếp. Bằng cách này, bạn giữ chức năng chính liên tục thời gian.

>>> A = [[3,5],[1,3],[6,1]] 
>>> B = [6,1,3] 
>>> srt = {b: i for i, b in enumerate(B)} 
>>> sorted(A, key=lambda x: srt[x[0]]) 
[[6, 1], [1, 3], [3, 5]] 

Chắc chắn có một vài cảnh báo trước mã này. Nếu một số được lặp lại trong B, bạn sẽ nhận được chỉ mục cho mục nhập cuối cùng được sử dụng trong sắp xếp.

Ngoài ra nếu có mục nhập trong A không được khớp trong B, bạn có KeyError. Bạn có thể giảm nhẹ phần này bằng cách sử dụng dict.get với một số giá trị mặc định, nhưng nếu dữ liệu đầu vào của bạn bị vặn để bắt đầu, lỗi là một điều tốt để nhận.

+0

Điều này dường như không cần thiết phức tạp với tôi. (Tôi muốn tìm hiểu những gì tôi nghĩ đơn giản hơn, nhưng tôi đã đăng một câu trả lời cho biết nó. Chỉ cần giải thích phần tóm tắt của tôi.) – jpmc26

+1

Một dict và một sắp xếp phức tạp! Vâng mỗi riêng của họ. Theo truyền thống, downvote có nghĩa là câu trả lời là sai (hoặc không hữu ích) và đây không phải là câu trả lời. Nó thường tốt hơn để có một phổ của câu trả lời có thể và đây là câu trả lời duy nhất cho thấy phương pháp này. –

0
sorted(A, key=lambda x: B.index(x[0])) 
+3

Bản sao giống hệt nhau của https://stackoverflow.com/a/46365677/4909087 –

2

Giả sử rằng AB có cùng độ dài, mỗi người trong số các yếu tố đầu tiên của bản ghi trong A tương ứng với một phần tử trong B và không có bản sao, bạn có thể sử dụng này:

>>> A = [[3,5],[1,3],[6,1]] 
>>> B = [6,1,3] 
>>> A_ind = {b: [b, a] for (b, a) in A} 
>>> [A_ind[b] for b in B] 
[[6, 1], [1, 3], [3, 5]] 

Điều này chỉ đơn giản là tạo ra một dict, ánh xạ phần b từ A đến toàn bộ các phần tử và tìm kiếm các phần tử tương ứng trong B trong đó dict. Sử dụng không sorted không index, điều này có độ phức tạp của O (n).

Nếu có thể được các yếu tố trùng lặp, bạn có thể tạo một dict (hoặc defaultdict) phím lập bản đồ vào danh sách các yếu tố có quan trọng mà:

>>> A = [[3,5],[1,3],[6,1],[1,4]] 
>>> A_ind = collections.defaultdict(list) 
>>> for b, a in A: 
...  A_ind[b].append([b,a]) 
...  
>>> B = [6,1,3,1] 
>>> [a for b in B for a in A_ind[b]] 
[[6, 1], [1, 3], [1, 4], [3, 5], [1, 3], [1, 4]] 

Hoặc xoay list vào iter ators để phân phối các giá trị trong A cho các phím phù hợp trong B:

>>> A_ind = {k: iter(v) for k, v in A_ind.items()} 
>>> [next(A_ind[b]) for b in B] 
[[6, 1], [1, 3], [3, 5], [1, 4]] 
Các vấn đề liên quan