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.

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.
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)]
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.
(def c (clojure.set/intersection (set a) (set b)))

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