I want to be able to keep the order of the list when it compares. Notice when I compare list1 with list2, it returns me 8 then 7 (reverse). How do I have it maintain the order?
>>> list1 = ['1','2','3','4','7','8']
>>> list2 = ['1','2','3','4','5','6']
>>> list(set(list2) - set(list1))
['5', '6']
>>> list(set(list1) - set(list2))
['8', '7']
An OrderedDict
makes a good substitute for an order-preserving set, since the keys views are set-like:
>>> from collections import OrderedDict
>>> list1 = ['1','2','3','4','7','8']
>>> list2 = ['1','2','3','4','5','6']
>>> OrderedDict.fromkeys(list1).keys() - OrderedDict.fromkeys(list2).keys()
{'7', '8'}
>>> OrderedDict.fromkeys(list2).keys() - OrderedDict.fromkeys(list1).keys()
{'5', '6'}
Strictly speaking, that may be still using implementation detail of CPython. But the list-comprehensions are not, and they're still O(n):
>>> od1 = OrderedDict.fromkeys(list1)
>>> od2 = OrderedDict.fromkeys(list2)
>>> [k for k in od1 if k not in od2]
['7', '8']
>>> [k for k in od2 if k not in od1]
['5', '6']
You can use a list comprehension:
list1 = ['1','2','3','4','7','8']
list2 = ['1','2','3','4','5','6']
set1 = set(list1) # convert to set for faster membership testing
result = [x for x in list2 if x not in set1]
# result: ['5', '6']
This will, however, include duplicate elements:
>>> list1 = [1]
>>> list2 = [1, 2, 2]
>>> set1 = set(list1)
>>> [x for x in list2 if x not in set1]
[2, 2]
If duplicates aren't desired, simply transform the list comprehension into a loop and keep track of all elements that you've already encountered:
list1 = [1]
list2 = [1, 2, 2]
set1 = set(list1)
result = []
for x in list2:
if x in set1:
continue
result.append(x)
set1.add(x)
# result: [2]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With