-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathidlist.go
102 lines (81 loc) · 2.01 KB
/
idlist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package tormenta
import (
"sort"
"github.com/jpincas/gouuidv6"
)
type idList []gouuidv6.UUID
func (ids idList) length() int {
return len(ids)
}
func (ids idList) sort(reverse bool) {
compareFunc := func(i, j int) bool {
return ids[i].Compare(ids[j])
}
if reverse {
compareFunc = func(i, j int) bool {
return ids[j].Compare(ids[i])
}
}
sort.Slice(ids, compareFunc)
}
// for OR
func union(listsOfIDs ...idList) (result idList) {
masterMap := map[gouuidv6.UUID]bool{}
for _, list := range listsOfIDs {
for _, id := range list {
masterMap[id] = true
}
}
for id := range masterMap {
result = append(result, id)
}
return result
}
// for AND
func intersection(listsOfIDs ...idList) (result idList) {
// Deal with emtpy and single list cases
if len(listsOfIDs) == 0 {
return
}
if len(listsOfIDs) == 1 {
result = listsOfIDs[0]
return
}
// Map out the IDs from each list,
// keeping a count of how many times each has appeared in a list
// In order that duplicates within a list don't count twice, we use a nested
// map to keep track of the contributions from the currently iterating list
// and only accept each IDs once
masterMap := map[gouuidv6.UUID]int{}
for _, list := range listsOfIDs {
thisListIDs := map[gouuidv6.UUID]bool{}
for _, id := range list {
if _, found := thisListIDs[id]; !found {
thisListIDs[id] = true
masterMap[id] = masterMap[id] + 1
}
}
}
// Only append an ID to the list if it has appeared
// in all the lists
for id, count := range masterMap {
if count == len(listsOfIDs) {
result = append(result, id)
}
}
return
}
var (
fixedID1 = gouuidv6.New()
fixedID2 = gouuidv6.New()
)
// isOr is a simple function to tell you wether a given combinator function is a union (or) or not
func isOr(combinator func(...idList) idList) bool {
n := combinator([]idList{
idList{fixedID1},
idList{fixedID2},
}...)
// If the combinator is AND, then it will want the ID to appear in both
// lists, thus giving a length of 0
return len(n) != 0
}