Find non-common elements in lists

Question:

I’m trying to write a piece of code that can automatically factor an expression. For example,
if I have two lists [1,2,3,4] and [2,3,5], the code should be able to find the common elements in the two lists, [2,3], and combine the rest of the elements together in a new list, being [1,4,5].

From this post: How to find list intersection?
I see that the common elements can be found by

set([1,2,3,4]&set([2,3,5]). 

Is there an easy way to retrieve non-common elements from each list, in my example being [1,4] and [5]?

I can go ahead and do a for loop:

lists = [[1,2,3,4],[2,3,5]]
conCommon = []
common = [2,3]
for elem in lists:
    for elem in eachList:
    if elem not in common:
        nonCommon += elem

But this seems redundant and inefficient. Does Python provide any handy function that can do that? Thanks in advance!!

Asked By: turtlesoup

||

Answers:

Use the symmetric difference operator for sets (aka the XOR operator):

>>> set([1,2,3]) ^ set([3,4,5])
set([1, 2, 4, 5])
Answered By: Amber

You can use Intersection concept to deal with this kind of problems.

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
set(b1).intersection(b2)
Out[22]: {4, 5}

Best thing about using this code is it works pretty fast for large data also. I have b1 with 607139 and b2 with 296029 elements when i use this logic I get my results in 2.9 seconds.

Answered By: saimadhu.polamuri

You can use the .__xor__ attribute method.

set([1,2,3,4]).__xor__(set([2,3,5]))

or

a = set([1,2,3,4])
b = set([2,3,5])
a.__xor__(b)
Answered By: SuperNova

Old question, but looks like python has a built-in function to provide exactly what you’re looking for: .difference().

EXAMPLE

list_one = [1,2,3,4]
list_two = [2,3,5]

one_not_two = set(list_one).difference(list_two)
# set([1, 4])

two_not_one = set(list_two).difference(list_one)
# set([5])

This could also be written as:

one_not_two = set(list_one) - set(list_two)

Timing

I ran some timing tests on both and it appears that .difference() has a slight edge, to the tune of 10 – 15% but each method took about an eighth of a second to filter 1M items (random integers between 500 and 100,000), so unless you’re very time sensitive, it’s probably immaterial.

Other Notes

It appears the OP is looking for a solution that provides two separate lists (or sets) – one where the first contains items not in the second, and vice versa. Most of the previous answers return a single list or set that include all of the items.

There is also the question as to whether items that may be duplicated in the first list should be counted multiple times, or just once.

If the OP wants to maintain duplicates, a list comprehension could be used, for example:

one_not_two = [ x for x in list_one if x not in list_two ]
two_not_one = [ x for x in list_two if x not in list_one ]

…which is roughly the same solution as posed in the original question, only a little cleaner. This method would maintain duplicates from the original list but is considerably (like multiple orders of magnitude) slower for larger data sets.

Answered By: elPastor

This should get the common and remaining elements

lis1=[1,2,3,4,5,6,2,3,1]
lis2=[4,5,8,7,10,6,9,8]

common = list(dict.fromkeys([l1 for l1 in lis1 if l1 in lis2]))
remaining = list(filter(lambda i: i not in common, lis1+lis2))

common = [4, 5, 6]

remaining = [1, 2, 3, 2, 3, 1, 8, 7, 10, 9, 8]

Answered By: Shahir Ansari

You can use symmetric_difference command

x = {1,2,3}
y = {2,3,4}

z = set.difference(x,y)

Output will be : z = {1,4}

Answered By: Gaurav Arora

All the good solutions, starting from basic DSA style to using inbuilt functions:

# Time: O(2n)
def solution1(arr1, arr2):
  map = {}
  maxLength = max(len(arr1), len(arr2))
  for i in range(maxLength):
    if(arr1[i]):
      if(not map.get(arr1[i])):
        map[arr1[i]] = [True, False]
      else:
        map[arr1[i]][0] = True
    if(arr2[i]):
      if(not map.get(arr2[i])):
        map[arr2[i]] = [False, True]
      else:
        map[arr2[i]][1] = False

  res = [];
  for key, value in map.items():
    if(value[0] == False or value[1] == False):
      res.append(key)

  return res

def solution2(arr1, arr2):
  return set(arr1) ^ set(arr2)

def solution3(arr1, arr2):
  return (set(arr1).difference(arr2), set(arr2).difference(arr1))

def solution4(arr1, arr2):
  return set(arr1).__xor__(set(arr2))

print(solution1([1,2,3], [2,4,6]))
print(solution2([1,2,3], [2,4,6]))
print(solution3([1,2,3], [2,4,6]))
print(solution4([1,2,3], [2,4,6]))
Answered By: Vinit Khandelwal