1package set
2
3// Union calculates the union of two or more sets
4func Union(set1, set2 Set, sets ...Set) Set {
5	u := set1.Copy()
6	set2.Each(func(item interface{}) bool {
7		u.Add(item)
8		return true
9	})
10
11	for _, set := range sets {
12		set.Each(func(item interface{}) bool {
13			u.Add(item)
14			return true
15		})
16	}
17
18	return u
19}
20
21// Intersection calculates the intersection of two or more sets
22func Intersection(set1, set2 Set, sets ...Set) Set {
23	all := Union(set1, set2, sets...)
24	result := Union(set1, set2, sets...)
25
26	all.Each(func(item interface{}) bool {
27		if !set1.Has(item) || !set2.Has(item) {
28			result.Remove(item)
29		}
30
31		for _, set := range sets {
32			if !set.Has(item) {
33				result.Remove(item)
34			}
35		}
36		return true
37	})
38	return result
39}
40
41// Difference calculates the difference of two or more sets
42func Difference(set1, set2 Set, sets ...Set) Set {
43	s := set1.Copy()
44	s.Separate(set2)
45	for _, set := range sets {
46		s.Separate(set) // seperate is thread safe
47	}
48	return s
49}
50
51// SymmetricDifference calculates the symmetric difference of two or more sets
52func SymmetricDifference(s Set, t Set) Set {
53	u := Difference(s, t)
54	v := Difference(t, s)
55	return Union(u, v)
56}
57