MetaTube / common /cluster /group.go
henry99a's picture
Clean commit for Hugging Face Spaces without binary files
ca7217f
package cluster
import (
"cmp"
"github.com/metatube-community/metatube-sdk-go/collection/unionfind"
)
type Group[T Locatable[T, R], R cmp.Ordered] struct {
Items []T
}
// GroupByDistance partitions a slice of items into proximity-based groups.
// Any two items whose DistanceTo value is less than or equal to the given
// threshold are considered to belong to the same group.
func GroupByDistance[T Locatable[T, R], R cmp.Ordered](items []T, threshold R) []Group[T, R] {
n := len(items)
uf := unionfind.NewQuickUnion(n)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
if items[i].DistanceTo(items[j]) <= threshold {
uf.Union(i, j)
}
}
}
groupMap := make(map[int][]T)
for i := 0; i < n; i++ {
root, _ := uf.Find(i)
groupMap[root] = append(groupMap[root], items[i])
}
var groups []Group[T, R]
for _, group := range groupMap {
groups = append(groups, Group[T, R]{
Items: group,
})
}
return groups
}