3

I am doing this problem a friend gave me where you are given 2 arrays say (a[1,2,3,4] and b[8,7,9,2,1]) and you have to find not common elements. Expected output is [3,4,8,7,9]. Code below.

def disjoint(e,f):
c = e[:]
d = f[:]
for i in range(len(e)):
    for j in range(len(f)):
        if e[i] == f[j]:
            c.remove(e[i])
            d.remove(d[j])
final = c + d
print(final)

print(disjoint(a,b))

I tried with nested loops and creating copies of given arrays to modify them then add them but...

def disjoint(e,f):
c = e[:]                      # list copies
d = f[:]
for i in range(len(e)):
    for j in range(len(f)):
        if e[i] == f[j]:
            c.remove(c[i])     # edited this line
            d.remove(d[j])
final = c + d
print(final)

print(disjoint(a,b))

when I try removing common element from list copies, I get different output [2,4,8,7,9]. why ?? This is my first question in this website. I'll be thankful if anyone can clear my doubts.

aloisdg
  • 22,270
  • 6
  • 85
  • 105
buda__
  • 41
  • 1
  • 5

2 Answers2

3

Using sets you can do:

a = [1,2,3,4]
b = [8,7,9,2,1]
diff = (set(a) | set(b)) - (set(a) & set(b))

(set(a) | set(b)) is the union, set(a) & set(b) is the intersection and finally you do the difference between the two sets using -.

Your bug comes when you remove the elements in the lines c.remove(c[i]) and d.remove(d[j]). Indeed, the common elements are e[i]and f[j] while c and d are the lists you are updating.
To fix your bug you only need to change these lines to c.remove(e[i]) and d.remove(f[j]).

Note also that your method to delete items in both lists will not work if a list may contain duplicates. Consider for instance the case a = [1,1,2,3,4] and b = [8,7,9,2,1].

abc
  • 11,579
  • 2
  • 26
  • 51
0

You can simplify your code to make it works:

def disjoint(e,f):
    c = e.copy() # [:] works also, but I think this is clearer
    d = f.copy()
    for i in e: # no need for index. just walk each items in the array
        for j in f:
            if i == j: # if there is a match, remove the match.
                c.remove(i)
                d.remove(j)
    return c + d

print(disjoint([1,2,3,4],[8,7,9,2,1]))

Try it online!

There are a lot of more effecient way to achieve this. Check this stack overflow question to discover them: Get difference between two lists. My favorite way is to use set (like in @newbie's answer). What is a set? Lets check the documentation:

A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. (For other containers see the built-in dict, list, and tuple classes, and the collections module.)

emphasis mine

Symmetric difference is perfect for our need!

Returns a new set with elements in either the set or the specified iterable but not both.

Ok here how to use it in your case:

def disjoint(e,f):
    return list(set(e).symmetric_difference(set(f)))

print(disjoint([1,2,3,4],[8,7,9,2,1]))

Try it online!

aloisdg
  • 22,270
  • 6
  • 85
  • 105