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 }