Files
obitools4/pkg/obiutils/ranks.go
Eric Coissac 2caaa62485 Implements the kmeans++ algo to select the landmarks in the geometric method
Former-commit-id: 732404a0dc6d7276e4e479dd2481aa4bd42d4ce5
2023-12-11 16:07:03 +01:00

97 lines
2.0 KiB
Go

package obiutils
import (
"sort"
)
// intRanker is a helper type for the rank function.
type intRanker struct {
x []int // Data to be ranked.
r []int // A list of indexes into f that reflects rank order after sorting.
}
// ranker satisfies the sort.Interface without mutating the reference slice, f.
func (r intRanker) Len() int { return len(r.x) }
func (r intRanker) Less(i, j int) bool { return r.x[r.r[i]] < r.x[r.r[j]] }
func (r intRanker) Swap(i, j int) { r.r[i], r.r[j] = r.r[j], r.r[i] }
// IntOrder sorts a slice of integers and returns a slice
// of indices that represents the order of the sorted
// elements.
//
// `data` is a slice of integers to be ordered.
// Returns a slice of the ordered indices.
func IntOrder(data []int) []int {
if len(data) == 0 {
return nil
}
r := make([]int, len(data))
rk := intRanker{
x: data,
r: r,
}
for i := 0; i < len(data); i++ {
rk.r[i] = i
}
sort.Sort(rk)
return r
}
func ReverseIntOrder(data []int) []int {
if len(data) == 0 {
return nil
}
r := make([]int, len(data))
rk := intRanker{
x: data,
r: r,
}
for i := 0; i < len(data); i++ {
rk.r[i] = i
}
sort.Sort(sort.Reverse(rk))
return r
}
type Ranker[T sort.Interface] struct {
x T // Data to be ranked.
r []int // A list of indexes into f that reflects rank order after sorting.
}
// ranker satisfies the sort.Interface without mutating the reference slice, f.
func (r Ranker[_]) Len() int { return len(r.r) }
func (r Ranker[T]) Less(i, j int) bool { return r.x.Less(r.r[i], r.r[j]) }
func (r Ranker[_]) Swap(i, j int) { r.r[i], r.r[j] = r.r[j], r.r[i] }
// Order sorts the given data using the provided sort.Interface and returns the sorted indices.
//
// data: The data to be sorted.
// Returns: A slice of integers representing the sorted indices.
func Order[T sort.Interface](data T) []int {
ldata := data.Len()
if ldata == 0 {
return nil
}
r := make([]int, ldata)
rk := Ranker[T]{
x: data,
r: r,
}
for i := 0; i < ldata; i++ {
rk.r[i] = i
}
sort.Stable(rk)
return r
}