-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslice.go
61 lines (50 loc) · 1.57 KB
/
slice.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
// Package search implements a simple binary search to allow finding the index
// of any element in an ordered slice of comparable elements
package search
import (
"golang.org/x/exp/constraints"
)
// Comparable exposes a method for comparing current struct, with another struct
type Comparable[T any] interface {
CompareTo(other T) int
}
// ComparableSlice takes an ordered slice of comparable elements (Comparable[T]) and the element to search for,
// and performs a binary search on the slice.
// It returns the index of given element, if found, or otherwise -1
func ComparableSlice[T Comparable[T]](slice []T, element T) int {
return search(slice, element, func(a, b T) int {
return a.CompareTo(b)
})
}
// Slice takes an ordered slice of comparable elements (constraints.Ordered) and the element to search for,
// and performs a binary search on the slice.
// It returns the index of given element, if found, or otherwise -1
func Slice[T constraints.Ordered](slice []T, element T) int {
return search(slice, element, func(a, b T) int {
if a > b {
return -1
}
if a < b {
return 1
}
return 0
})
}
// search uses binary search to find the index of the given element
func search[T any](slice []T, element T, compare func(a, b T) int) int {
start := 0
end := len(slice) - 1
middle := (start + end) / 2
for compare(slice[middle], element) != 0 && start <= end {
if compare(slice[middle], element) >= 1 {
start = middle + 1
} else {
end = middle - 1
}
middle = (start + end) / 2
}
if compare(slice[middle], element) == 0 {
return middle
}
return -1
}