Documentation
¶
Overview ¶
Package dedup provides generic duplicate and near-duplicate detection for text-like values using string hash strategies.
Index ¶
- func Canonicalize[T any](groups [][]T, better func(a, b T) bool) []T
- func CanonicalizeWith[T any](groups [][]T, better func(a, b T) bool, merge func(winner, loser T)) []T
- type ContentHasher
- type Detector
- func (d *Detector[T]) FindDuplicateGroups() []DuplicateGroup[T]
- func (d *Detector[T]) FindDuplicates() [][]T
- func (d *Detector[T]) FindNearDuplicates(threshold int) [][]T
- func (d *Detector[T]) GetStats() map[string]any
- func (d *Detector[T]) Index(items []T)
- func (d *Detector[T]) Stats() Stats
- func (d *Detector[T]) WithOrdering(less func(a, b T) bool) *Detector[T]
- type DuplicateGroup
- type HashingStrategy
- type Stats
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Canonicalize ¶
Canonicalize reduces each duplicate group to a single representative. For each group it keeps the element for which better(candidate, current) reports the candidate as preferable, returning one survivor per group in input order. Empty groups are skipped; a singleton group yields that element unchanged. Pair this with Detector.FindDuplicateGroups / FindNearDuplicates.
func CanonicalizeWith ¶
func CanonicalizeWith[T any](groups [][]T, better func(a, b T) bool, merge func(winner, loser T)) []T
CanonicalizeWith is Canonicalize plus a merge step: for every non-winner in a group, merge(winner, loser) is invoked before the loser is discarded — e.g. to fold a duplicate's metadata into the survivor. With a pointer element type, merge can mutate the winner in place. merge may be nil.
Types ¶
type ContentHasher ¶
type ContentHasher struct {
// contains filtered or unexported fields
}
ContentHasher provides fast duplicate detection capabilities
func NewContentHasher ¶
func NewContentHasher(strategy HashingStrategy) *ContentHasher
NewContentHasher creates a new content hasher with the specified strategy. SimHash shingle size and bit width default to 3-grams and 64 bits; override with WithSimHashOptions.
func (*ContentHasher) HashContent ¶
func (ch *ContentHasher) HashContent(content string) string
HashContent generates a hash for the given content using the configured strategy
func (*ContentHasher) SupportsNearDuplicate ¶
func (ch *ContentHasher) SupportsNearDuplicate() bool
SupportsNearDuplicate reports whether the strategy produces locality-sensitive hashes usable by FindNearDuplicates.
func (*ContentHasher) WithSimHashOptions ¶
func (ch *ContentHasher) WithSimHashOptions(shingleSize, bits int) *ContentHasher
WithSimHashOptions configures the SimHash shingle (n-gram) size and bit width, returning the receiver for chaining (matching Detector.WithOrdering). Invalid values are clamped to the supported range rather than erroring, matching the package's tolerant input handling: shingleSize is clamped to a minimum of 1; bits is clamped to the range 1..64 (the internal FNV-64 / uint64 pipeline and Detector.hammingDistance cannot represent wider hashes).
type Detector ¶
type Detector[T any] struct { // contains filtered or unexported fields }
Detector groups items by content hash to find exact and near duplicates.
func NewDetector ¶
func NewDetector[T any](strategy HashingStrategy, content func(T) string) *Detector[T]
NewDetector creates a new duplicate detector for items of type T.
func (*Detector[T]) FindDuplicateGroups ¶
func (d *Detector[T]) FindDuplicateGroups() []DuplicateGroup[T]
FindDuplicateGroups returns groups of duplicate items with their shared hash.
func (*Detector[T]) FindDuplicates ¶
func (d *Detector[T]) FindDuplicates() [][]T
FindDuplicates returns groups of duplicate items.
Example ¶
package main
import (
"fmt"
"github.com/dotcommander/reliquary/dedup"
)
type Doc struct {
ID string
Body string
}
func main() {
docs := []Doc{
{ID: "doc1", Body: "The quick brown fox"},
{ID: "doc2", Body: "the quick brown fox"},
{ID: "doc3", Body: "Something completely different"},
}
// Index using NormalizedHash (ignores case and whitespace differences)
d := dedup.NewDetector(dedup.NormalizedHash, func(doc Doc) string {
return doc.Body
})
d.Index(docs)
for _, group := range d.FindDuplicates() {
fmt.Printf("Duplicate group of %d items:\n", len(group))
for _, doc := range group {
fmt.Printf(" - %s: %s\n", doc.ID, doc.Body)
}
}
}
Output: Duplicate group of 2 items: - doc1: The quick brown fox - doc2: the quick brown fox
func (*Detector[T]) FindNearDuplicates ¶
FindNearDuplicates finds items with similar hashes (for SimHash).
Example ¶
package main
import (
"fmt"
"github.com/dotcommander/reliquary/dedup"
)
type Doc struct {
ID string
Body string
}
func main() {
docs := []Doc{
{ID: "doc1", Body: "The quick brown fox jumps over the lazy dog"},
{ID: "doc2", Body: "The quick brown fox jumps over the lazy dog today"},
{ID: "doc3", Body: "Different text altogether"},
}
// Index using SimHash for near-duplicate (fuzzy similarity) matching
d := dedup.NewDetector(dedup.SimHash, func(doc Doc) string {
return doc.Body
})
d.Index(docs)
// Group items within a Hamming distance threshold of 5
for _, group := range d.FindNearDuplicates(5) {
fmt.Printf("Near-duplicate cluster of %d items:\n", len(group))
for _, doc := range group {
fmt.Printf(" - %s: %s\n", doc.ID, doc.Body)
}
}
}
Output: Near-duplicate cluster of 2 items: - doc1: The quick brown fox jumps over the lazy dog - doc2: The quick brown fox jumps over the lazy dog today
func (*Detector[T]) Index ¶
func (d *Detector[T]) Index(items []T)
Index creates a hash index for all items.
func (*Detector[T]) WithOrdering ¶
WithOrdering sets the ordering used to sort items within duplicate groups.
type DuplicateGroup ¶
DuplicateGroup is a group of items that share the same content hash.
type HashingStrategy ¶
type HashingStrategy string
HashingStrategy defines different approaches to content hashing
const ( // SimpleHash - Basic content hash SimpleHash HashingStrategy = "simple" // NormalizedHash - Normalized text hash (whitespace, case insensitive) NormalizedHash HashingStrategy = "normalized" // SemanticHash - Content-aware hash (structure preserved) SemanticHash HashingStrategy = "semantic" // SimHash - Locality-sensitive hash (Charikar 2002) for similarity detection SimHash HashingStrategy = "simhash" )