forked from cortexproject/cortex
/
by_id.go
92 lines (85 loc) · 1.74 KB
/
by_id.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
package chunk
// ByID allow you to sort chunks by ID
type ByID []Chunk
func (cs ByID) Len() int { return len(cs) }
func (cs ByID) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
func (cs ByID) Less(i, j int) bool { return cs[i].ID < cs[j].ID }
// unique will remove duplicates from the input
func unique(cs ByID) ByID {
if len(cs) == 0 {
return nil
}
result := make(ByID, 1, len(cs))
result[0] = cs[0]
i, j := 0, 1
for j < len(cs) {
if result[i].ID == cs[j].ID {
j++
continue
}
result = append(result, cs[j])
i++
j++
}
return result
}
// merge will merge & dedupe two lists of chunks.
// list musts be sorted and not contain dupes.
func merge(a, b ByID) ByID {
result := make(ByID, 0, len(a)+len(b))
i, j := 0, 0
for i < len(a) && j < len(b) {
if a[i].ID < b[j].ID {
result = append(result, a[i])
i++
} else if a[i].ID > b[j].ID {
result = append(result, b[j])
j++
} else {
result = append(result, a[i])
i++
j++
}
}
for ; i < len(a); i++ {
result = append(result, a[i])
}
for ; j < len(b); j++ {
result = append(result, b[j])
}
return result
}
// nWayIntersect will interesct n sorted lists of chunks.
func nWayIntersect(sets []ByID) ByID {
l := len(sets)
switch l {
case 0:
return ByID{}
case 1:
return sets[0]
case 2:
var (
left, right = sets[0], sets[1]
i, j = 0, 0
result = []Chunk{}
)
for i < len(left) && j < len(right) {
if left[i].ID == right[j].ID {
result = append(result, left[i])
}
if left[i].ID < right[j].ID {
i++
} else {
j++
}
}
return result
default:
var (
split = l / 2
left = nWayIntersect(sets[:split])
right = nWayIntersect(sets[split:])
)
return nWayIntersect([]ByID{left, right})
}
}