algorithm: partition 2 arrays into "only in A", "intersection of A & B", & "only in B"

Viewed 91

I have a situation where I have two arrays and I need to partition them so that I end up with 3 arrays:

  • elements that are only in A
  • elements that are only in B
  • elements that are in both A and B

Example:

A = [1, 4, 3, 2]
B = [2, 6, 5, 3]
3part(A,B) => [[1,4], [6,5], [2,3]] # the order of the elements in each array doesn't matter

I've come up with a correct solution, but wonder if it could be quicker. It is (in pseudocode):

3part(A,B) =>
    a_only = []
    b_only = []
    intersect = []

    foreach a in A
        if B.contains(a)
            intersect.push(a)
        else
            a_only.push(a)

    foreach b in B
        if not intersect.contains(b)
            b_only.push(b)

    return [a_only, b_only, intersect]

In my case at hand, A & B will each contain up to 5000 complex structures (instead of ints) and it runs in about 1.5 secs. It gets used as part of a user interaction which can happen frequently, so ideally it would take < .5sec .

BTW, is there a name for this operation as a whole, other than "difference-difference-intersection"?

Thanks!

EDIT:

Based on the suggestions to use a hash, my updated code runs in under 40ms :-D

Here is the pseudocode:

(say that "key" is the element that I am using for comparison)

array_to_hash(A, Key)
    h = {}
    foreach a in A
        h[a[Key]] = a
    return h

3part(A,B) =>
    a_only = []
    b_only = []
    intersect = {} // note this is now a hash instead of array

    Ah = array_to_hash(A, 'key')
    Bh = array_to_hash(B, 'key')

    foreach ak in Ah.keys()
        if Bh.hasKey(ak)
            intersect[ak] = Ah[ak]
        else
            a_only.push(Ah[ak])

    foreach bk in Bh.keys()
        if not intersect.hasKey(bk)
            b_only.push(Bh[bk])

    return [a_only, b_only, intersect.values]

Thank you all for the suggestions.

3 Answers
Related