2016-12-13 34 views
17

Tôi đang làm việc với các danh sách và tôi cần phải so sánh chúng để tạo danh sách các phần tử cụ thể mới. Ví dụ:Python tìm các phần tử trong một danh sách không nằm trong một danh sách khác

main_list=[] 
list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 

Tôi cần phải xếp vào danh sách_1 và nối thêm vào main_list = [] tất cả các yếu tố không khớp trong danh sách_2.

Kết quả sẽ là thế này:

main_list=["f", "m"] 

Làm thế nào tôi có thể làm điều đó với python?

+1

Bạn đang tìm kiếm các yếu tố trong 'list_2' xuất hiện nơi nào trong' list_1' hoặc các yếu tố trong 'list_2' không có trong cùng một chỉ mục trong' list_1'? –

Trả lời

8

(1) Bạn có thể sử dụng số setdiff1d của NumPy. Từ response of Chinny84, nếu bạn đang quan tâm đến yếu tố độc đáo, sau đó:

import numpy as np 
list_1 = ["a", "b", "c", "d", "e"] 
list_2 = ["a", "f", "c", "m"] 
main_list = np.setdiff1d(list_2,list_1) 

(2) Nếu không, sử dụng main_list = np.setdiff1d(list_2,list_1, assume_unique=True)

Cả hai câu trả lời sẽ cung cấp cho bạn ["f", "m"]. Tuy nhiên, nếu list_2 = ["a", "f", "c", "m", "m"], câu trả lời (1) sản lượng ["f", "m"] Câu trả lời BUT (2) cho ["f", "m", "m"] (vì tính duy nhất của mỗi phần tử trong list_2 là không quan trọng).

1

Tôi sẽ zip các danh sách với nhau để so sánh chúng với phần tử theo phần tử.

main_list = [b for a, b in zip(list1, list2) if a!= b] 
+0

Nếu OP muốn so sánh phần tử theo phần tử (không rõ ràng, ví dụ có thể theo một trong hai cách), đây là _much_ hiệu quả hơn các câu trả lời khác, vì đây là một giá rẻ duy nhất trên cả danh sách 'list's with single new ' 'đang được xây dựng, không có thêm thời gian, không có kiểm tra ngăn chặn tốn kém, v.v. – ShadowRanger

+0

@ShadowRanger điều này sẽ chỉ làm việc cho sự khác biệt yếu tố khôn ngoan mà là một điểm quan trọng –

+0

@fordprefect: Yup. [Câu trả lời của riêng tôi] (https://stackoverflow.com/a/41126821/364696) bao gồm các khác biệt độc lập về vị trí. – ShadowRanger

34

Bạn có thể sử dụng bộ:

main_list = list(set(list_2) - set(list_1)) 

Output:

>>> list_1=["a", "b", "c", "d", "e"] 
>>> list_2=["a", "f", "c", "m"] 
>>> set(list_2) - set(list_1) 
set(['m', 'f']) 
>>> list(set(list_2) - set(list_1)) 
['m', 'f'] 

mỗi comment @JonClements', đây là một phiên bản ngăn nắp:

>>> list_1=["a", "b", "c", "d", "e"] 
>>> list_2=["a", "f", "c", "m"] 
>>> list(set(list_2).difference(list_1)) 
['m', 'f'] 
+0

Điều này là tốt nếu chúng ta chỉ quan tâm đến các phần tử 'duy nhất' nhưng nếu chúng ta có nhiều' m'', ví dụ như điều này sẽ không nhận được nó. – Chinny84

+0

Đó là sự thật. Tôi cho rằng tấm áp phích đang tìm kiếm các yếu tố độc đáo. Tôi cho rằng nó phụ thuộc vào ý của anh ấy bằng "cụ thể". – nrlakin

+0

Thật vậy p.s. Tôi đã không bỏ phiếu cho câu trả lời của bạn, đặc biệt là cho một câu hỏi ban đầu không rõ ràng. – Chinny84

10

Sử dụng một list comprehension như thế này:

main_list = [item for item in list_2 if item not in list_1] 

Output:

>>> list_1 = ["a", "b", "c", "d", "e"] 
>>> list_2 = ["a", "f", "c", "m"] 
>>> 
>>> main_list = [item for item in list_2 if item not in list_1] 
>>> main_list 
['f', 'm'] 
+1

Lưu ý: Đối với 'list_1' lớn hơn, bạn muốn chuyển sang' set'/'frozenset', ví dụ: 'set_1 = frozenset (list_1)', sau đó 'main_list = [mục cho mục trong danh sách_2 nếu mục không nằm trong set_1]', giảm thời gian kiểm tra từ 'O (n)' trên mỗi mục thành (xấp xỉ) 'O (1)' . – ShadowRanger

3
main_list=[] 
list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 

for i in list_2: 
    if i not in list_1: 
     main_list.append(i) 

print(main_list) 

đầu ra:

['f', 'm'] 
+0

Giống như [giải pháp dựa trên danh sách tương đương] (http://stackoverflow.com/a/41125957/364696), điều này sẽ chậm nếu 'list_1' lớn và' list_2' có kích thước không nhỏ, vì nó liên quan đến 'len (list_2)' 'O (n)' quét của 'list_1', làm cho nó' O (n * m) '(trong đó' n' và 'm' là độ dài của' list_2' và 'list_1' tương ứng). Nếu bạn chuyển đổi 'list_1' thành' set'/'frozenset' ở phía trước, các kiểm tra chứa có thể được thực hiện trong' O (1) ', làm cho tổng công việc' O (n) 'trên độ dài' list_2' (về mặt kỹ thuật, 'O (max (n, m))', vì bạn thực hiện 'O (m)' để tạo 'bộ'). – ShadowRanger

0

Nếu số lần xuất hiện nên được đưa vào tài khoản của bạn có thể cần phải sử dụng một cái gì đó giống như collections.Counter:

list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 
from collections import Counter 
cnt1 = Counter(list_1) 
cnt2 = Counter(list_2) 
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts] 

>>> final 
['f', 'm'] 

Như đã hứa điều này cũng có thể xử lý số lần xuất hiện khác nhau như "sự khác biệt":

list_1=["a", "b", "c", "d", "e", 'a'] 
cnt1 = Counter(list_1) 
cnt2 = Counter(list_2) 
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts] 

>>> final 
['a', 'f', 'm'] 
1

Nếu bạn muốn có một giải pháp một liner (bỏ qua nhập khẩu) mà chỉ yêu cầu O(max(n, m)) làm việc cho các đầu vào có độ dài nm, không O(n * m) làm việc, bạn có thể làm như vậy với the itertools module:

from itertools import filterfalse 

main_list = list(filterfalse(set(list_1).__contains__, list_2)) 

này có lợi thế trong những chức năng chức năng tham gia một hàm callback về xây dựng ion, cho phép nó tạo ra các cuộc gọi lại một lần và tái sử dụng nó cho mọi phần tử mà không cần lưu trữ nó ở đâu đó (vì filterfalse lưu trữ nó trong nội bộ); danh sách hiểu và biểu thức máy phát điện có thể làm điều này, nhưng nó xấu xí.†

Đó được kết quả tương tự trong một dòng duy nhất là:

main_list = [x for x in list_2 if x not in list_1] 

với tốc độ:

set_1 = set(list_1) 
main_list = [x for x in list_2 if x not in set_1] 

Tất nhiên, nếu so sánh được dự định được vị trí, vì vậy:

list_1 = [1, 2, 3] 
list_2 = [2, 3, 4] 

phải xuất:

main_list = [2, 3, 4] 

(vì giá trị trong list_2 có một trận đấu ở các chỉ số tương tự trong list_1), bạn nên chắc chắn đi với Patrick's answer, trong đó bao gồm không list s tạm thời hoặc set s (ngay cả với set s là khoảng O(1), họ có một cao hơn "hằng số" yếu tố trên mỗi séc so với kiểm tra bình đẳng đơn giản) và liên quan đến công việc O(min(n, m)), ít hơn bất kỳ câu trả lời nào khác và nếu vấn đề của bạn nhạy cảm vị trí, chỉ là giải pháp đúng khi các yếu tố phù hợp xuất hiện ở vị trí không khớp.

†: Các cách để làm điều tương tự với một sự hiểu biết danh sách như một lớp lót sẽ được lạm dụng lồng looping để tạo và giá trị bộ nhớ cache (s) trong vòng lặp "ngoài cùng", ví dụ:

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1] 

cũng cung cấp một lợi ích hiệu suất nhỏ trên Python 3 (vì bây giờ set_1 được kiểm tra cục bộ trong mã hiểu, thay vì tra cứu từ phạm vi lồng nhau cho mỗi kiểm tra; trên Python 2 không quan trọng, vì Python 2 không sử dụng các bao đóng để hiểu danh sách; chúng hoạt động trong cùng phạm vi mà chúng được sử dụng).

10

Không chắc tại sao những lời giải thích trên là quá phức tạp khi bạn có phương pháp tự nhiên có sẵn:

main_list = list(set(list_2)-set(list_1)) 
+0

Thứ tự bảo quản có thể là lý do – Keith

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