Logo

Programming-Idioms

This language bar is your friend. Select your favorite languages!
  • Go

Idiom #218 List intersection

Create the list c containing all unique elements that are contained in both lists a and b.
c should not contain any duplicates, even if a and b do.
The order of c doesn't matter.

func intersection[S ~[]T, T comparable](a, b S) S {
	seta := make(map[T]bool, len(a))
	for _, x := range a {
		seta[x] = true
	}
	setb := make(map[T]bool, len(b))
	for _, y := range b {
		setb[y] = true
	}

	var c S
	for x := range seta {
		if setb[x] {
			c = append(c, x)
		}
	}
	return c
}

Convert to sets, then iterate in one pass.
The runtime cost is O(n).
The final order is indeterminate.
Works for any type parameter T.
func intersection[S ~[]T, T comparable](a, b S) S {
	s, l := a, b
	if len(b) < len(a) {
		s, l = b, a
	}

	set := make(map[T]struct{}, len(s))
	for _, x := range s {
		set[x] = struct{}{}
	}

	c := make(S, 0, len(s))
	for _, x := range l {
		if _, found := set[x]; found {
			c = append(c, x)
			delete(set, x)
		}
	}
	return c
}

Convert the smallest slices to a set, then iterate on the other slice to see which elements are also in the set.
Duplicate elements are ignored.
The final order is indeterminate.
Works for any comparable type T.


Complexity: O(N) [N = len(a)+len(b)]
Memory: O(N) [N = min(len(a), len(b)]
seta := make(map[T]bool, len(a))
for _, x := range a {
	seta[x] = true
}
setb := make(map[T]bool, len(a))
for _, y := range b {
	setb[y] = true
}

var c []T
for x := range seta {
	if setb[x] {
		c = append(c, x)
	}
}

Convert to sets, then iterate in one pass.
The runtime cost is O(n).
Elements have type T.
The final order is indeterminate.
(def c (clojure.set/intersection (set a) (set b)))

New implementation...
< >
programming-idioms.org