Nhận sự khác biệt giữa hai danh sách


810

Tôi có hai danh sách trong Python, như thế này:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

Tôi cần tạo một danh sách thứ ba với các mục từ danh sách đầu tiên không có trong danh sách thứ hai. Từ ví dụ tôi phải lấy:

temp3 = ['Three', 'Four']

Có cách nào nhanh mà không cần chu kỳ và kiểm tra không?


14
Là các yếu tố được đảm bảo duy nhất? Nếu bạn có temp1 = ['One', 'One', 'One']temp2 = ['One'], bạn có muốn ['One', 'One']quay lại, hay []?
Michael Mrozek

@ michael-mrozek họ là duy nhất.
Max Frai

12
Bạn có muốn giữ trật tự của các yếu tố?
Mark Byers

Câu trả lời:


1209
In [5]: list(set(temp1) - set(temp2))
Out[5]: ['Four', 'Three']

Coi chừng

In [5]: set([1, 2]) - set([2, 3])
Out[5]: set([1]) 

nơi bạn có thể mong đợi / muốn nó bằng nhau set([1, 3]). Nếu bạn muốn set([1, 3])làm câu trả lời của mình, bạn sẽ cần sử dụng set([1, 2]).symmetric_difference(set([2, 3])).


27
@Drewdin: Danh sách không hỗ trợ toán hạng "-". Bộ, tuy nhiên, làm, và những gì được thể hiện ở trên nếu bạn nhìn kỹ.
Godsmith

1
cảm ơn, tôi đã kết thúc bằng cách sử dụng bộ (ListA) .symmetric_difference (ListB)
Drewdin

43
sự khác biệt đối xứng có thể được viết bằng: ^ (set1 ^ set2)
Bastian

10
Xin vui lòng, bạn có thể chỉnh sửa câu trả lời của bạn và chỉ ra rằng điều này chỉ trả về temp1-temp2? .. Như đã nói khác để trả về tất cả các khác biệt bạn phải sử dụng chênh lệch sysmetric: list (set (temp1) ^ set (temp2))
rkachach 16/2/2016

Tại sao tôi nhận được TypeError: 'str' object is not callablekhi tôi thực hiện thao tác này vào a = [1,2,2,2,3]b = [2]
d8aninja

476

Tất cả các giải pháp hiện có đều cung cấp một hoặc một trong những:

  • Hiệu suất nhanh hơn O (n * m).
  • Giữ nguyên thứ tự của danh sách đầu vào.

Nhưng cho đến nay không có giải pháp nào có cả. Nếu bạn muốn cả hai, hãy thử điều này:

s = set(temp2)
temp3 = [x for x in temp1 if x not in s]

Kiểm tra hiệu suất

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print timeit.timeit('list(set(temp1) - set(temp2))', init, number = 100000)
print timeit.timeit('s = set(temp2);[x for x in temp1 if x not in s]', init, number = 100000)
print timeit.timeit('[item for item in temp1 if item not in temp2]', init, number = 100000)

Các kết quả:

4.34620224079 # ars' answer
4.2770634955  # This answer
30.7715615392 # matt b's answer

Phương pháp tôi đã trình bày cũng như giữ trật tự cũng nhanh hơn (một chút) so với phép trừ tập hợp vì nó không yêu cầu xây dựng một tập hợp không cần thiết. Sự khác biệt hiệu suất sẽ đáng chú ý hơn nếu danh sách đầu tiên dài hơn đáng kể so với danh sách thứ hai và nếu băm là tốn kém. Đây là một thử nghiệm thứ hai chứng minh điều này:

init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''

Các kết quả:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer

2
Hỗ trợ bổ sung cho câu trả lời này: Chạy qua một trường hợp sử dụng trong đó việc giữ trật tự danh sách là quan trọng đối với hiệu suất. Khi làm việc với các đối tượng tarinfo hoặc zipinfo, tôi đã sử dụng phép trừ đặt. Để loại trừ các đối tượng tarinfo nhất định khỏi bị trích xuất từ ​​kho lưu trữ. Tạo danh sách mới là nhanh nhưng siêu chậm trong quá trình trích xuất. Lý do trốn tránh tôi lúc đầu. Hóa ra việc sắp xếp lại danh sách các đối tượng tarinfo đã gây ra một hình phạt hiệu suất rất lớn. Chuyển sang phương pháp hiểu danh sách lưu trong ngày.
Ray Thompson

@MarkByer - có lẽ tôi nên viết một câu hỏi hoàn toàn mới cho việc này. Nhưng làm thế nào điều này sẽ làm việc trong một forloop? Chẳng hạn, nếu temp1 và temp2 của tôi tiếp tục thay đổi .. và tôi muốn nối thêm thông tin mới vào temp3?
Ason

@MarkByer - nghe hay đấy. Tôi sẽ tiếp tục suy nghĩ về nó một chút. nhưng +1 cho một giải pháp tuyệt vời.
Ason

Tôi đồng ý với @Dejel >>> temp1 = ['Một', 'Hai', 'Ba', 'Bốn'] >>> temp2 = ['Một', 'Hai', 'Sáu'] >>> s = đặt (temp2) >>> temp3 = [x cho x trong temp1 nếu x không ở s] >>> temp3 ['Three', 'Four']
Earlonrails

3
@haccks Vì kiểm tra tư cách thành viên của danh sách là thao tác O (n) (lặp trên toàn bộ danh sách), nhưng kiểm tra tư cách thành viên của một bộ là O (1).
Mark Byers

86
temp3 = [item for item in temp1 if item not in temp2]

15
Biến temp2thành một bộ trước đó sẽ làm cho điều này hiệu quả hơn một chút.
lunaryorn

3
Đúng, tùy thuộc vào việc Ockonal có quan tâm đến việc trùng lặp hay không (câu hỏi ban đầu không nói)
matt b

2
Nhận xét nói rằng (danh sách | bộ dữ liệu) không có bản sao.

1
Tôi đánh giá cao câu trả lời của bạn bởi vì tôi nghĩ ban đầu bạn đã đúng về các bản sao. Nhưng item not in temp2item not in set(temp2)sẽ luôn trả lại kết quả tương tự, bất kể có trùng lặp hay không temp2.
arekolek

5
Lên bình chọn cho việc không yêu cầu danh sách các mục có thể được băm.
Brent

23

Có thể tìm thấy sự khác biệt giữa hai danh sách (giả sử list1 và list2) bằng cách sử dụng hàm đơn giản sau.

def diff(list1, list2):
    c = set(list1).union(set(list2))  # or c = set(list1) | set(list2)
    d = set(list1).intersection(set(list2))  # or d = set(list1) & set(list2)
    return list(c - d)

hoặc là

def diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))  # or return list(set(list1) ^ set(list2))

Bằng cách sử dụng chức năng trên, sự khác biệt có thể được tìm thấy bằng cách sử dụng diff(temp2, temp1)hoặc diff(temp1, temp2). Cả hai sẽ cho kết quả['Four', 'Three'] . Bạn không phải lo lắng về thứ tự của danh sách hoặc danh sách nào sẽ được đưa ra đầu tiên.

Tài liệu tham khảo Python


7
Tại sao không đặt (list1) .symmetric_difference (set (list2))?
vui vẻ

20

Trong trường hợp bạn muốn sự khác biệt theo cách đệ quy, tôi đã viết một gói cho python: https://github.com/seperman/deepdiff

Cài đặt

Cài đặt từ PyPi:

pip install deepdiff

Ví dụ sử dụng

Nhập khẩu

>>> from deepdiff import DeepDiff
>>> from pprint import pprint
>>> from __future__ import print_function # In case running on Python 2

Cùng một đối tượng trả về sản phẩm nào

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = t1
>>> print(DeepDiff(t1, t2))
{}

Loại vật phẩm đã thay đổi

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:"2", 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{ 'type_changes': { 'root[2]': { 'newtype': <class 'str'>,
                                 'newvalue': '2',
                                 'oldtype': <class 'int'>,
                                 'oldvalue': 2}}}

Giá trị của một mặt hàng đã thay đổi

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

Mục được thêm và / hoặc loại bỏ

>>> t1 = {1:1, 2:2, 3:3, 4:4}
>>> t2 = {1:1, 2:4, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff)
{'dic_item_added': ['root[5]', 'root[6]'],
 'dic_item_removed': ['root[4]'],
 'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

Chênh lệch chuỗi

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world"}}
>>> t2 = {1:1, 2:4, 3:3, 4:{"a":"hello", "b":"world!"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { 'root[2]': {'newvalue': 4, 'oldvalue': 2},
                      "root[4]['b']": { 'newvalue': 'world!',
                                        'oldvalue': 'world'}}}

Chuỗi chênh lệch 2

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world!\nGoodbye!\n1\n2\nEnd"}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n1\n2\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { "root[4]['b']": { 'diff': '--- \n'
                                                '+++ \n'
                                                '@@ -1,5 +1,4 @@\n'
                                                '-world!\n'
                                                '-Goodbye!\n'
                                                '+world\n'
                                                ' 1\n'
                                                ' 2\n'
                                                ' End',
                                        'newvalue': 'world\n1\n2\nEnd',
                                        'oldvalue': 'world!\n'
                                                    'Goodbye!\n'
                                                    '1\n'
                                                    '2\n'
                                                    'End'}}}

>>> 
>>> print (ddiff['values_changed']["root[4]['b']"]["diff"])
--- 
+++ 
@@ -1,5 +1,4 @@
-world!
-Goodbye!
+world
 1
 2
 End

Thay đổi loại

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n\n\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'type_changes': { "root[4]['b']": { 'newtype': <class 'str'>,
                                      'newvalue': 'world\n\n\nEnd',
                                      'oldtype': <class 'list'>,
                                      'oldvalue': [1, 2, 3]}}}

Danh sách khác biệt

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3, 4]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{'iterable_item_removed': {"root[4]['b'][2]": 3, "root[4]['b'][3]": 4}}

Danh sách khác biệt 2:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'iterable_item_added': {"root[4]['b'][3]": 3},
  'values_changed': { "root[4]['b'][1]": {'newvalue': 3, 'oldvalue': 2},
                      "root[4]['b'][2]": {'newvalue': 2, 'oldvalue': 3}}}

Liệt kê sự khác biệt bỏ qua thứ tự hoặc trùng lặp: (có cùng từ điển như trên)

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2, ignore_order=True)
>>> print (ddiff)
{}

Danh sách có chứa từ điển:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:1, 2:2}]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:3}]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'dic_item_removed': ["root[4]['b'][2][2]"],
  'values_changed': {"root[4]['b'][2][1]": {'newvalue': 3, 'oldvalue': 1}}}

Bộ:

>>> t1 = {1, 2, 8}
>>> t2 = {1, 2, 3, 5}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (DeepDiff(t1, t2))
{'set_item_added': ['root[3]', 'root[5]'], 'set_item_removed': ['root[8]']}

Được đặt tên là Tuples:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> t1 = Point(x=11, y=22)
>>> t2 = Point(x=11, y=23)
>>> pprint (DeepDiff(t1, t2))
{'values_changed': {'root.y': {'newvalue': 23, 'oldvalue': 22}}}

Đối tượng tùy chỉnh:

>>> class ClassA(object):
...     a = 1
...     def __init__(self, b):
...         self.b = b
... 
>>> t1 = ClassA(1)
>>> t2 = ClassA(2)
>>> 
>>> pprint(DeepDiff(t1, t2))
{'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}

Thuộc tính đối tượng được thêm vào:

>>> t2.c = "new attribute"
>>> pprint(DeepDiff(t1, t2))
{'attribute_added': ['root.c'],
 'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}

20

Có thể được thực hiện bằng cách sử dụng toán tử python XOR.

  • Điều này sẽ loại bỏ các bản sao trong mỗi danh sách
  • Điều này sẽ cho thấy sự khác biệt của temp1 từ temp2 và temp2 từ temp1.

set(temp1) ^ set(temp2)

hoạt động, nhưng tại sao?
ZakS

Câu trả lời hay nhất!
Artsiom Praneuski

Thật là một câu trả lời! thật trớ trêu !!!! tuyệt vời
toing_toing

18

cách đơn giản nhất,

sử dụng set (). sự khác biệt (set ())

list_a = [1,2,3]
list_b = [2,3]
print set(list_a).difference(set(list_b))

câu trả lời là set([1])

có thể in như một danh sách,

print list(set(list_a).difference(set(list_b)))

14

Nếu bạn đang thực sự nhìn vào hiệu suất, sau đó sử dụng numpy!

Dưới đây là cuốn sổ tay đầy đủ như một ý chính trên github với sự so sánh giữa danh sách, numpy và gấu trúc.

https://gist.github.com/denfromufa/2821ff59b02e9482be15d27f2bbd4451

nhập mô tả hình ảnh ở đây


tôi đã cập nhật sổ ghi chép trong liên kết và cả ảnh chụp màn hình. Đáng ngạc nhiên là gấu trúc chậm hơn numpy ngay cả khi chuyển sang hashtable trong nội bộ. Một phần điều này có thể do upcasting đến int64.
denfromufa

13

Tôi sẽ đưa vào vì không có giải pháp hiện tại nào mang lại một tuple:

temp3 = tuple(set(temp1) - set(temp2))

cách khác:

#edited using @Mark Byers idea. If you accept this one as answer, just accept his instead.
temp3 = tuple(x for x in temp1 if x not in set(temp2))

Giống như các câu trả lời không mang lại khác theo hướng này, nó giữ trật tự


11

Tôi muốn một cái gì đó sẽ có hai danh sách và có thể làm những gì difftrongbash đó. Vì câu hỏi này xuất hiện đầu tiên khi bạn tìm kiếm "python diff hai danh sách" và không cụ thể lắm, tôi sẽ đăng những gì tôi nghĩ ra.

Sử dụng SequenceMathertừ difflibbạn có thể so sánh hai danh sách như thế diff. Không có câu trả lời nào khác sẽ cho bạn biết vị trí xảy ra sự khác biệt, nhưng câu trả lời này thì có. Một số câu trả lời cho sự khác biệt chỉ theo một hướng. Một số sắp xếp lại các yếu tố. Một số không xử lý trùng lặp. Nhưng giải pháp này cung cấp cho bạn một sự khác biệt thực sự giữa hai danh sách:

a = 'A quick fox jumps the lazy dog'.split()
b = 'A quick brown mouse jumps over the dog'.split()

from difflib import SequenceMatcher

for tag, i, j, k, l in SequenceMatcher(None, a, b).get_opcodes():
  if tag == 'equal': print('both have', a[i:j])
  if tag in ('delete', 'replace'): print('  1st has', a[i:j])
  if tag in ('insert', 'replace'): print('  2nd has', b[k:l])

Kết quả này:

both have ['A', 'quick']
  1st has ['fox']
  2nd has ['brown', 'mouse']
both have ['jumps']
  2nd has ['over']
both have ['the']
  1st has ['lazy']
both have ['dog']

Tất nhiên, nếu ứng dụng của bạn đưa ra các giả định tương tự như các câu trả lời khác đưa ra, bạn sẽ được hưởng lợi từ chúng nhiều nhất. Nhưng nếu bạn đang tìm kiếm một sự thậtdiff chức năng , thì đây là cách duy nhất để đi.

Ví dụ: không có câu trả lời nào khác có thể xử lý:

a = [1,2,3,4,5]
b = [5,4,3,2,1]

Nhưng cái này thì có:

  2nd has [5, 4, 3, 2]
both have [1]
  1st has [2, 3, 4, 5]


10

điều này có thể còn nhanh hơn cả việc hiểu danh sách của Mark:

list(itertools.filterfalse(set(temp2).__contains__, temp1))

7
Có thể muốn bao gồm các from itertools import filterfalsebit ở đây. Cũng lưu ý rằng điều này không trả về một chuỗi như những cái khác, nó trả về một trình vòng lặp.
Matt Luongo

7

Đây là một Countercâu trả lời cho trường hợp đơn giản nhất.

Cái này ngắn hơn cái ở trên mà khác hai chiều bởi vì nó chỉ thực hiện chính xác những gì câu hỏi yêu cầu: tạo ra một danh sách những gì trong danh sách đầu tiên chứ không phải thứ hai.

from collections import Counter

lst1 = ['One', 'Two', 'Three', 'Four']
lst2 = ['One', 'Two']

c1 = Counter(lst1)
c2 = Counter(lst2)
diff = list((c1 - c2).elements())

Ngoài ra, tùy thuộc vào sở thích dễ đọc của bạn, nó tạo ra một lớp lót tốt:

diff = list((Counter(lst1) - Counter(lst2)).elements())

Đầu ra:

['Three', 'Four']

Lưu ý rằng bạn có thể loại bỏ list(...) cuộc gọi nếu bạn chỉ lặp lại cuộc gọi đó.

Bởi vì giải pháp này sử dụng bộ đếm, nó xử lý số lượng đúng so với nhiều câu trả lời dựa trên tập hợp. Ví dụ về đầu vào này:

lst1 = ['One', 'Two', 'Two', 'Two', 'Three', 'Three', 'Four']
lst2 = ['One', 'Two']

Đầu ra là:

['Two', 'Two', 'Three', 'Three', 'Four']

5

Bạn có thể sử dụng một phương thức ngây thơ nếu các yếu tố của danh sách khuếch tán được sắp xếp và thiết lập.

list1=[1,2,3,4,5]
list2=[1,2,3]

print list1[len(list2):]

hoặc với các phương thức thiết lập riêng:

subset=set(list1).difference(list2)

print subset

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print "Naive solution: ", timeit.timeit('temp1[len(temp2):]', init, number = 100000)
print "Native set solution: ", timeit.timeit('set(temp1).difference(temp2)', init, number = 100000)

Dung dịch ngây thơ: 0,0787101593292

Giải pháp thiết lập gốc: 0.998837615564


5

Tôi hơi quá muộn trong trò chơi này nhưng bạn có thể so sánh hiệu suất của một số mã được đề cập ở trên với điều này, hai trong số các ứng cử viên nhanh nhất là,

list(set(x).symmetric_difference(set(y)))
list(set(x) ^ set(y))

Tôi xin lỗi vì mức độ cơ bản của mã hóa.

import time
import random
from itertools import filterfalse

# 1 - performance (time taken)
# 2 - correctness (answer - 1,4,5,6)
# set performance
performance = 1
numberoftests = 7

def answer(x,y,z):
    if z == 0:
        start = time.clock()
        lists = (str(list(set(x)-set(y))+list(set(y)-set(y))))
        times = ("1 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 1:
        start = time.clock()
        lists = (str(list(set(x).symmetric_difference(set(y)))))
        times = ("2 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 2:
        start = time.clock()
        lists = (str(list(set(x) ^ set(y))))
        times = ("3 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 3:
        start = time.clock()
        lists = (filterfalse(set(y).__contains__, x))
        times = ("4 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 4:
        start = time.clock()
        lists = (tuple(set(x) - set(y)))
        times = ("5 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 5:
        start = time.clock()
        lists = ([tt for tt in x if tt not in y])
        times = ("6 = " + str(time.clock() - start))
        return (lists,times)

    else:    
        start = time.clock()
        Xarray = [iDa for iDa in x if iDa not in y]
        Yarray = [iDb for iDb in y if iDb not in x]
        lists = (str(Xarray + Yarray))
        times = ("7 = " + str(time.clock() - start))
        return (lists,times)

n = numberoftests

if performance == 2:
    a = [1,2,3,4,5]
    b = [3,2,6]
    for c in range(0,n):
        d = answer(a,b,c)
        print(d[0])

elif performance == 1:
    for tests in range(0,10):
        print("Test Number" + str(tests + 1))
        a = random.sample(range(1, 900000), 9999)
        b = random.sample(range(1, 900000), 9999)
        for c in range(0,n):
            #if c not in (1,4,5,6):
            d = answer(a,b,c)
            print(d[1])

5

Dưới đây là một vài cách đơn giản, giữ gìn trật tự biệt hai danh sách các chuỗi.

Một cách tiếp cận khác thường sử dụng pathlib :

import pathlib


temp1 = ["One", "Two", "Three", "Four"]
temp2 = ["One", "Two"]

p = pathlib.Path(*temp1)
r = p.relative_to(*temp2)
list(r.parts)
# ['Three', 'Four']

Giả định này cả hai danh sách đều chứa các chuỗi có khởi đầu tương đương. Xem tài liệu để biết thêm chi tiết. Lưu ý, nó không đặc biệt nhanh so với các thao tác thiết lập.


Một triển khai đơn giản bằng cách sử dụng itertools.zip_longest:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']

1
Giải pháp itertools chỉ hoạt động khi các phần tử trong temp1temp2xếp hàng tốt. Ví dụ: nếu bạn xoay quanh các phần tử trong temp2hoặc chèn một số giá trị khác vào đầu temp2, listcomp sẽ chỉ trả về các phần tử giống như trongtemp1
KenHBS

Vâng, nó là một tính năng của các phương pháp này. Như đã đề cập, các giải pháp này là bảo toàn trật tự - chúng giả định một số thứ tự tương đối giữa các danh sách. Một giải pháp không có thứ tự sẽ là khác biệt hai bộ.
pylang

4

Đây là một giải pháp khác:

def diff(a, b):
    xa = [i for i in set(a) if i not in b]
    xb = [i for i in set(b) if i not in a]
    return xa + xb


4

Hãy nói rằng chúng tôi có hai danh sách

list1 = [1, 3, 5, 7, 9]
list2 = [1, 2, 3, 4, 5]

chúng ta có thể thấy từ hai danh sách trên mà các mục 1, 3, 5 tồn tại trong list2 và các mục 7, 9 thì không. Mặt khác, các mục 1, 3, 5 tồn tại trong danh sách 1 và các mục 2, 4 thì không.

Giải pháp tốt nhất để trả về một danh sách mới chứa các mục 7, 9 và 2, 4 là gì?

Tất cả các câu trả lời ở trên tìm ra giải pháp, bây giờ cái gì là tối ưu nhất?

def difference(list1, list2):
    new_list = []
    for i in list1:
        if i not in list2:
            new_list.append(i)

    for j in list2:
        if j not in list1:
            new_list.append(j)
    return new_list

đấu với

def sym_diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))

Sử dụng timeit chúng ta có thể thấy kết quả

t1 = timeit.Timer("difference(list1, list2)", "from __main__ import difference, 
list1, list2")
t2 = timeit.Timer("sym_diff(list1, list2)", "from __main__ import sym_diff, 
list1, list2")

print('Using two for loops', t1.timeit(number=100000), 'Milliseconds')
print('Using two for loops', t2.timeit(number=100000), 'Milliseconds')

trả lại

[7, 9, 2, 4]
Using two for loops 0.11572412995155901 Milliseconds
Using symmetric_difference 0.11285737506113946 Milliseconds

Process finished with exit code 0

3

phiên bản đơn của giải pháp arulmr

def diff(listA, listB):
    return set(listA) - set(listB) | set(listA) -set(listB)

3

nếu bạn muốn một cái gì đó giống như một bộ thay đổi ... có thể sử dụng Counter

from collections import Counter

def diff(a, b):
  """ more verbose than needs to be, for clarity """
  ca, cb = Counter(a), Counter(b)
  to_add = cb - ca
  to_remove = ca - cb
  changes = Counter(to_add)
  changes.subtract(to_remove)
  return changes

lista = ['one', 'three', 'four', 'four', 'one']
listb = ['one', 'two', 'three']

In [127]: diff(lista, listb)
Out[127]: Counter({'two': 1, 'one': -1, 'four': -2})
# in order to go from lista to list b, you need to add a "two", remove a "one", and remove two "four"s

In [128]: diff(listb, lista)
Out[128]: Counter({'four': 2, 'one': 1, 'two': -1})
# in order to go from listb to lista, you must add two "four"s, add a "one", and remove a "two"

2

Chúng ta có thể tính toán giao điểm trừ liên kết danh sách:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two', 'Five']

set(temp1+temp2)-(set(temp1)&set(temp2))

Out: set(['Four', 'Five', 'Three']) 

2

Điều này có thể được giải quyết với một dòng. Câu hỏi được đưa ra hai danh sách (temp1 và temp2) trả về sự khác biệt của chúng trong danh sách thứ ba (temp3).

temp3 = list(set(temp1).difference(set(temp2)))

1

Đây là một cách đơn giản để phân biệt hai danh sách (bất kể nội dung là gì), bạn có thể nhận được kết quả như dưới đây:

>>> from sets import Set
>>>
>>> l1 = ['xvda', False, 'xvdbb', 12, 'xvdbc']
>>> l2 = ['xvda', 'xvdbb', 'xvdbc', 'xvdbd', None]
>>>
>>> Set(l1).symmetric_difference(Set(l2))
Set([False, 'xvdbd', None, 12])

Hy vọng điều này sẽ hữu ích.


0

Tôi thích sử dụng chuyển đổi thành tập hợp và sau đó sử dụng hàm "differ ()". Mã đầy đủ là:

temp1 = ['One', 'Two', 'Three', 'Four'  ]                   
temp2 = ['One', 'Two']
set1 = set(temp1)
set2 = set(temp2)
set3 = set1.difference(set2)
temp3 = list(set3)
print(temp3)

Đầu ra:

>>>print(temp3)
['Three', 'Four']

Đây là cách dễ nhất để hoàn tác và chuyển đổi trong tương lai nếu bạn làm việc với dữ liệu lớn, chuyển đổi nó thành các bộ sẽ loại bỏ trùng lặp nếu không cần phải sao chép. Hy vọng nó giúp ;-)


-1
(list(set(a)-set(b))+list(set(b)-set(a)))

3
Ngoài việc cung cấp câu trả lời, bạn có thể đưa ra lời giải thích cho cách thức hoạt động / áp dụng cho vấn đề cụ thể này không? Câu trả lời và giải pháp là tuyệt vời, nhưng hướng dẫn và giải thích chi tiết là vô cùng tốt hơn.
Busse

-1
def diffList(list1, list2):     # returns the difference between two lists.
    if len(list1) > len(list2):
        return (list(set(list1) - set(list2)))
    else:
        return (list(set(list2) - set(list1)))

ví dụ: list1 = [10, 15, 20, 25, 30, 35, 40]list2 = [25, 40, 35]sau đó danh sách trả về sẽ làoutput = [10, 20, 30, 15]


Bạn không thể làm như thế này cho hoạt động khác biệt. Ngay cả trong trường hợp số nguyên, nếu bạn yêu cầu một hàm thực hiện 'a - b', thì chỉ nên trừ 'b' khỏi 'a', bất kể 'b' có lớn hơn 'a' hay không. Tương tự là trường hợp với danh sách và bộ. Cả A - B và B - A đều có thể là các hoạt động hợp lệ bất kể độ dài của A và B, bạn chỉ cần loại trừ nội dung của B khỏi A để thực hiện A - B.
Abu Talha Đan Mạch
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.